Merge pull request #9777 from Snuffleupagus/PageViewport-MessageHandler-cleanup
Various `PageViewport` and `MessageHandler` cleanup
This commit is contained in:
commit
76337fdc49
14
gulpfile.js
14
gulpfile.js
@ -883,24 +883,16 @@ gulp.task('lib', ['buildnumber'], function () {
|
|||||||
var licenseHeaderLibre =
|
var licenseHeaderLibre =
|
||||||
fs.readFileSync('./src/license_header_libre.js').toString();
|
fs.readFileSync('./src/license_header_libre.js').toString();
|
||||||
var preprocessor2 = require('./external/builder/preprocessor2.js');
|
var preprocessor2 = require('./external/builder/preprocessor2.js');
|
||||||
var sharedFiles = [
|
|
||||||
'compatibility',
|
|
||||||
'global_scope',
|
|
||||||
'is_node',
|
|
||||||
'streams_polyfill',
|
|
||||||
'util',
|
|
||||||
];
|
|
||||||
var buildLib = merge([
|
var buildLib = merge([
|
||||||
gulp.src([
|
gulp.src([
|
||||||
'src/{core,display}/*.js',
|
'src/{core,display,shared}/*.js',
|
||||||
'src/shared/{' + sharedFiles.join() + '}.js',
|
'!src/shared/{cffStandardStrings,fonts_utils}.js',
|
||||||
'src/{pdf,pdf.worker}.js',
|
'src/{pdf,pdf.worker}.js',
|
||||||
], { base: 'src/', }),
|
], { base: 'src/', }),
|
||||||
gulp.src([
|
gulp.src([
|
||||||
'examples/node/domstubs.js',
|
'examples/node/domstubs.js',
|
||||||
'web/*.js',
|
'web/*.js',
|
||||||
'!web/pdfjs.js',
|
'!web/{pdfjs,viewer}.js',
|
||||||
'!web/viewer.js',
|
|
||||||
], { base: '.', }),
|
], { base: '.', }),
|
||||||
gulp.src('test/unit/*.js', { base: '.', }),
|
gulp.src('test/unit/*.js', { base: '.', }),
|
||||||
]).pipe(transform('utf8', preprocess))
|
]).pipe(transform('utf8', preprocess))
|
||||||
|
@ -15,12 +15,13 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
arrayByteLength, arraysToBytes, assert, createPromiseCapability, info,
|
arrayByteLength, arraysToBytes, assert, createPromiseCapability, info,
|
||||||
InvalidPDFException, MessageHandler, MissingPDFException, PasswordException,
|
InvalidPDFException, MissingPDFException, PasswordException,
|
||||||
setVerbosityLevel, UnexpectedResponseException, UnknownErrorException,
|
setVerbosityLevel, UnexpectedResponseException, UnknownErrorException,
|
||||||
UNSUPPORTED_FEATURES, warn, XRefParseException
|
UNSUPPORTED_FEATURES, warn, XRefParseException
|
||||||
} from '../shared/util';
|
} from '../shared/util';
|
||||||
import { LocalPdfManager, NetworkPdfManager } from './pdf_manager';
|
import { LocalPdfManager, NetworkPdfManager } from './pdf_manager';
|
||||||
import isNodeJS from '../shared/is_node';
|
import isNodeJS from '../shared/is_node';
|
||||||
|
import { MessageHandler } from '../shared/message_handler';
|
||||||
import { Ref } from './primitives';
|
import { Ref } from './primitives';
|
||||||
|
|
||||||
var WorkerTask = (function WorkerTaskClosure() {
|
var WorkerTask = (function WorkerTaskClosure() {
|
||||||
|
@ -16,13 +16,12 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
assert, createPromiseCapability, getVerbosityLevel, info, InvalidPDFException,
|
assert, createPromiseCapability, getVerbosityLevel, info, InvalidPDFException,
|
||||||
isArrayBuffer, isNum, isSameOrigin, MessageHandler, MissingPDFException,
|
isArrayBuffer, isNum, isSameOrigin, MissingPDFException, NativeImageDecoding,
|
||||||
NativeImageDecoding, PageViewport, PasswordException, setVerbosityLevel,
|
PasswordException, setVerbosityLevel, shadow, stringToBytes,
|
||||||
shadow, stringToBytes, UnexpectedResponseException, UnknownErrorException,
|
UnexpectedResponseException, UnknownErrorException, unreachable, Util, warn
|
||||||
unreachable, Util, warn
|
|
||||||
} from '../shared/util';
|
} from '../shared/util';
|
||||||
import {
|
import {
|
||||||
DOMCanvasFactory, DOMCMapReaderFactory, DummyStatTimer,
|
DOMCanvasFactory, DOMCMapReaderFactory, DummyStatTimer, PageViewport,
|
||||||
RenderingCancelledException, StatTimer
|
RenderingCancelledException, StatTimer
|
||||||
} from './dom_utils';
|
} from './dom_utils';
|
||||||
import { FontFaceObject, FontLoader } from './font_loader';
|
import { FontFaceObject, FontLoader } from './font_loader';
|
||||||
@ -30,6 +29,7 @@ import { apiCompatibilityParams } from './api_compatibility';
|
|||||||
import { CanvasGraphics } from './canvas';
|
import { CanvasGraphics } from './canvas';
|
||||||
import globalScope from '../shared/global_scope';
|
import globalScope from '../shared/global_scope';
|
||||||
import { GlobalWorkerOptions } from './worker_options';
|
import { GlobalWorkerOptions } from './worker_options';
|
||||||
|
import { MessageHandler } from '../shared/message_handler';
|
||||||
import { Metadata } from './metadata';
|
import { Metadata } from './metadata';
|
||||||
import { PDFDataTransportStream } from './transport_stream';
|
import { PDFDataTransportStream } from './transport_stream';
|
||||||
import { WebGLContext } from './webgl';
|
import { WebGLContext } from './webgl';
|
||||||
@ -885,7 +885,12 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
|||||||
* along with transforms required for rendering.
|
* along with transforms required for rendering.
|
||||||
*/
|
*/
|
||||||
getViewport(scale, rotate = this.rotate, dontFlip = false) {
|
getViewport(scale, rotate = this.rotate, dontFlip = false) {
|
||||||
return new PageViewport(this.view, scale, rotate, 0, 0, dontFlip);
|
return new PageViewport({
|
||||||
|
viewBox: this.view,
|
||||||
|
scale,
|
||||||
|
rotation: rotate,
|
||||||
|
dontFlip,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* @param {GetAnnotationsParameters} params - Annotation parameters.
|
* @param {GetAnnotationsParameters} params - Annotation parameters.
|
||||||
@ -1200,7 +1205,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
class LoopbackPort {
|
class LoopbackPort {
|
||||||
constructor(defer) {
|
constructor(defer = true) {
|
||||||
this._listeners = [];
|
this._listeners = [];
|
||||||
this._defer = defer;
|
this._defer = defer;
|
||||||
this._deferred = Promise.resolve(undefined);
|
this._deferred = Promise.resolve(undefined);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
assert, CMapCompressionType, removeNullCharacters, stringToBytes,
|
assert, CMapCompressionType, removeNullCharacters, stringToBytes,
|
||||||
unreachable, warn
|
unreachable, Util, warn
|
||||||
} from '../shared/util';
|
} from '../shared/util';
|
||||||
|
|
||||||
const DEFAULT_LINK_REL = 'noopener noreferrer nofollow';
|
const DEFAULT_LINK_REL = 'noopener noreferrer nofollow';
|
||||||
@ -135,6 +135,158 @@ class DOMSVGFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} PageViewportParameters
|
||||||
|
* @property {Array} viewBox - The xMin, yMin, xMax and yMax coordinates.
|
||||||
|
* @property {number} scale - The scale of the viewport.
|
||||||
|
* @property {number} rotation - The rotation, in degrees, of the viewport.
|
||||||
|
* @property {number} offsetX - (optional) The vertical, i.e. x-axis, offset.
|
||||||
|
* The default value is `0`.
|
||||||
|
* @property {number} offsetY - (optional) The horizontal, i.e. y-axis, offset.
|
||||||
|
* The default value is `0`.
|
||||||
|
* @property {boolean} dontFlip - (optional) If true, the x-axis will not be
|
||||||
|
* flipped. The default value is `false`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} PageViewportCloneParameters
|
||||||
|
* @property {number} scale - (optional) The scale, overriding the one in the
|
||||||
|
* cloned viewport. The default value is `this.scale`.
|
||||||
|
* @property {number} rotation - (optional) The rotation, in degrees, overriding
|
||||||
|
* the one in the cloned viewport. The default value is `this.rotation`.
|
||||||
|
* @property {boolean} dontFlip - (optional) If true, the x-axis will not be
|
||||||
|
* flipped. The default value is `false`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PDF page viewport created based on scale, rotation and offset.
|
||||||
|
*/
|
||||||
|
class PageViewport {
|
||||||
|
/**
|
||||||
|
* @param {PageViewportParameters}
|
||||||
|
*/
|
||||||
|
constructor({ viewBox, scale, rotation, offsetX = 0, offsetY = 0,
|
||||||
|
dontFlip = false, }) {
|
||||||
|
this.viewBox = viewBox;
|
||||||
|
this.scale = scale;
|
||||||
|
this.rotation = rotation;
|
||||||
|
this.offsetX = offsetX;
|
||||||
|
this.offsetY = offsetY;
|
||||||
|
|
||||||
|
// creating transform to convert pdf coordinate system to the normal
|
||||||
|
// canvas like coordinates taking in account scale and rotation
|
||||||
|
let centerX = (viewBox[2] + viewBox[0]) / 2;
|
||||||
|
let centerY = (viewBox[3] + viewBox[1]) / 2;
|
||||||
|
let rotateA, rotateB, rotateC, rotateD;
|
||||||
|
rotation = rotation % 360;
|
||||||
|
rotation = rotation < 0 ? rotation + 360 : rotation;
|
||||||
|
switch (rotation) {
|
||||||
|
case 180:
|
||||||
|
rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
|
||||||
|
break;
|
||||||
|
case 90:
|
||||||
|
rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
|
||||||
|
break;
|
||||||
|
case 270:
|
||||||
|
rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
|
||||||
|
break;
|
||||||
|
// case 0:
|
||||||
|
default:
|
||||||
|
rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dontFlip) {
|
||||||
|
rotateC = -rotateC; rotateD = -rotateD;
|
||||||
|
}
|
||||||
|
|
||||||
|
let offsetCanvasX, offsetCanvasY;
|
||||||
|
let width, height;
|
||||||
|
if (rotateA === 0) {
|
||||||
|
offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
|
||||||
|
offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
|
||||||
|
width = Math.abs(viewBox[3] - viewBox[1]) * scale;
|
||||||
|
height = Math.abs(viewBox[2] - viewBox[0]) * scale;
|
||||||
|
} else {
|
||||||
|
offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
|
||||||
|
offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
|
||||||
|
width = Math.abs(viewBox[2] - viewBox[0]) * scale;
|
||||||
|
height = Math.abs(viewBox[3] - viewBox[1]) * scale;
|
||||||
|
}
|
||||||
|
// creating transform for the following operations:
|
||||||
|
// translate(-centerX, -centerY), rotate and flip vertically,
|
||||||
|
// scale, and translate(offsetCanvasX, offsetCanvasY)
|
||||||
|
this.transform = [
|
||||||
|
rotateA * scale,
|
||||||
|
rotateB * scale,
|
||||||
|
rotateC * scale,
|
||||||
|
rotateD * scale,
|
||||||
|
offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
|
||||||
|
offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
|
||||||
|
];
|
||||||
|
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clones viewport, with optional additional properties.
|
||||||
|
* @param {PageViewportCloneParameters} - (optional)
|
||||||
|
* @return {PageViewport} Cloned viewport.
|
||||||
|
*/
|
||||||
|
clone({ scale = this.scale, rotation = this.rotation,
|
||||||
|
dontFlip = false, } = {}) {
|
||||||
|
return new PageViewport({
|
||||||
|
viewBox: this.viewBox.slice(),
|
||||||
|
scale,
|
||||||
|
rotation,
|
||||||
|
offsetX: this.offsetX,
|
||||||
|
offsetY: this.offsetY,
|
||||||
|
dontFlip,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts PDF point to the viewport coordinates. For examples, useful for
|
||||||
|
* converting PDF location into canvas pixel coordinates.
|
||||||
|
* @param {number} x - The x-coordinate.
|
||||||
|
* @param {number} y - The y-coordinate.
|
||||||
|
* @return {Object} Object containing `x` and `y` properties of the
|
||||||
|
* point in the viewport coordinate space.
|
||||||
|
* @see {@link convertToPdfPoint}
|
||||||
|
* @see {@link convertToViewportRectangle}
|
||||||
|
*/
|
||||||
|
convertToViewportPoint(x, y) {
|
||||||
|
return Util.applyTransform([x, y], this.transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts PDF rectangle to the viewport coordinates.
|
||||||
|
* @param {Array} rect - The xMin, yMin, xMax and yMax coordinates.
|
||||||
|
* @return {Array} Array containing corresponding coordinates of the rectangle
|
||||||
|
* in the viewport coordinate space.
|
||||||
|
* @see {@link convertToViewportPoint}
|
||||||
|
*/
|
||||||
|
convertToViewportRectangle(rect) {
|
||||||
|
let tl = Util.applyTransform([rect[0], rect[1]], this.transform);
|
||||||
|
let br = Util.applyTransform([rect[2], rect[3]], this.transform);
|
||||||
|
return [tl[0], tl[1], br[0], br[1]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts viewport coordinates to the PDF location. For examples, useful
|
||||||
|
* for converting canvas pixel location into PDF one.
|
||||||
|
* @param {number} x - The x-coordinate.
|
||||||
|
* @param {number} y - The y-coordinate.
|
||||||
|
* @return {Object} Object containing `x` and `y` properties of the
|
||||||
|
* point in the PDF coordinate space.
|
||||||
|
* @see {@link convertToViewportPoint}
|
||||||
|
*/
|
||||||
|
convertToPdfPoint(x, y) {
|
||||||
|
return Util.applyInverseTransform([x, y], this.transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var RenderingCancelledException = (function RenderingCancelledException() {
|
var RenderingCancelledException = (function RenderingCancelledException() {
|
||||||
function RenderingCancelledException(msg, type) {
|
function RenderingCancelledException(msg, type) {
|
||||||
this.message = msg;
|
this.message = msg;
|
||||||
@ -277,6 +429,7 @@ class DummyStatTimer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
PageViewport,
|
||||||
RenderingCancelledException,
|
RenderingCancelledException,
|
||||||
addLinkAttributes,
|
addLinkAttributes,
|
||||||
getFilenameFromUrl,
|
getFilenameFromUrl,
|
||||||
|
446
src/shared/message_handler.js
Normal file
446
src/shared/message_handler.js
Normal file
@ -0,0 +1,446 @@
|
|||||||
|
/* Copyright 2018 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
AbortException, assert, createPromiseCapability, MissingPDFException,
|
||||||
|
ReadableStream, UnexpectedResponseException, UnknownErrorException
|
||||||
|
} from './util';
|
||||||
|
|
||||||
|
function resolveCall(fn, args, thisArg = null) {
|
||||||
|
if (!fn) {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
resolve(fn.apply(thisArg, args));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapReason(reason) {
|
||||||
|
if (typeof reason !== 'object') {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
switch (reason.name) {
|
||||||
|
case 'AbortException':
|
||||||
|
return new AbortException(reason.message);
|
||||||
|
case 'MissingPDFException':
|
||||||
|
return new MissingPDFException(reason.message);
|
||||||
|
case 'UnexpectedResponseException':
|
||||||
|
return new UnexpectedResponseException(reason.message, reason.status);
|
||||||
|
default:
|
||||||
|
return new UnknownErrorException(reason.message, reason.details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeReasonSerializable(reason) {
|
||||||
|
if (!(reason instanceof Error) ||
|
||||||
|
reason instanceof AbortException ||
|
||||||
|
reason instanceof MissingPDFException ||
|
||||||
|
reason instanceof UnexpectedResponseException ||
|
||||||
|
reason instanceof UnknownErrorException) {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
return new UnknownErrorException(reason.message, reason.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveOrReject(capability, success, reason) {
|
||||||
|
if (success) {
|
||||||
|
capability.resolve();
|
||||||
|
} else {
|
||||||
|
capability.reject(reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finalize(promise) {
|
||||||
|
return Promise.resolve(promise).catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function MessageHandler(sourceName, targetName, comObj) {
|
||||||
|
this.sourceName = sourceName;
|
||||||
|
this.targetName = targetName;
|
||||||
|
this.comObj = comObj;
|
||||||
|
this.callbackId = 1;
|
||||||
|
this.streamId = 1;
|
||||||
|
this.postMessageTransfers = true;
|
||||||
|
this.streamSinks = Object.create(null);
|
||||||
|
this.streamControllers = Object.create(null);
|
||||||
|
let callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
|
||||||
|
let ah = this.actionHandler = Object.create(null);
|
||||||
|
|
||||||
|
this._onComObjOnMessage = (event) => {
|
||||||
|
let data = event.data;
|
||||||
|
if (data.targetName !== this.sourceName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.stream) {
|
||||||
|
this._processStreamMessage(data);
|
||||||
|
} else if (data.isReply) {
|
||||||
|
let callbackId = data.callbackId;
|
||||||
|
if (data.callbackId in callbacksCapabilities) {
|
||||||
|
let callback = callbacksCapabilities[callbackId];
|
||||||
|
delete callbacksCapabilities[callbackId];
|
||||||
|
if ('error' in data) {
|
||||||
|
callback.reject(wrapReason(data.error));
|
||||||
|
} else {
|
||||||
|
callback.resolve(data.data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(`Cannot resolve callback ${callbackId}`);
|
||||||
|
}
|
||||||
|
} else if (data.action in ah) {
|
||||||
|
let action = ah[data.action];
|
||||||
|
if (data.callbackId) {
|
||||||
|
let sourceName = this.sourceName;
|
||||||
|
let targetName = data.sourceName;
|
||||||
|
Promise.resolve().then(function () {
|
||||||
|
return action[0].call(action[1], data.data);
|
||||||
|
}).then((result) => {
|
||||||
|
comObj.postMessage({
|
||||||
|
sourceName,
|
||||||
|
targetName,
|
||||||
|
isReply: true,
|
||||||
|
callbackId: data.callbackId,
|
||||||
|
data: result,
|
||||||
|
});
|
||||||
|
}, (reason) => {
|
||||||
|
comObj.postMessage({
|
||||||
|
sourceName,
|
||||||
|
targetName,
|
||||||
|
isReply: true,
|
||||||
|
callbackId: data.callbackId,
|
||||||
|
error: makeReasonSerializable(reason),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if (data.streamId) {
|
||||||
|
this._createStreamSink(data);
|
||||||
|
} else {
|
||||||
|
action[0].call(action[1], data.data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unknown action from worker: ${data.action}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
comObj.addEventListener('message', this._onComObjOnMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageHandler.prototype = {
|
||||||
|
on(actionName, handler, scope) {
|
||||||
|
var ah = this.actionHandler;
|
||||||
|
if (ah[actionName]) {
|
||||||
|
throw new Error(`There is already an actionName called "${actionName}"`);
|
||||||
|
}
|
||||||
|
ah[actionName] = [handler, scope];
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Sends a message to the comObj to invoke the action with the supplied data.
|
||||||
|
* @param {String} actionName - Action to call.
|
||||||
|
* @param {JSON} data - JSON data to send.
|
||||||
|
* @param {Array} [transfers] - Optional list of transfers/ArrayBuffers
|
||||||
|
*/
|
||||||
|
send(actionName, data, transfers) {
|
||||||
|
var message = {
|
||||||
|
sourceName: this.sourceName,
|
||||||
|
targetName: this.targetName,
|
||||||
|
action: actionName,
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
this.postMessage(message, transfers);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Sends a message to the comObj to invoke the action with the supplied data.
|
||||||
|
* Expects that the other side will callback with the response.
|
||||||
|
* @param {String} actionName - Action to call.
|
||||||
|
* @param {JSON} data - JSON data to send.
|
||||||
|
* @param {Array} [transfers] - Optional list of transfers/ArrayBuffers.
|
||||||
|
* @returns {Promise} Promise to be resolved with response data.
|
||||||
|
*/
|
||||||
|
sendWithPromise(actionName, data, transfers) {
|
||||||
|
var callbackId = this.callbackId++;
|
||||||
|
var message = {
|
||||||
|
sourceName: this.sourceName,
|
||||||
|
targetName: this.targetName,
|
||||||
|
action: actionName,
|
||||||
|
data,
|
||||||
|
callbackId,
|
||||||
|
};
|
||||||
|
var capability = createPromiseCapability();
|
||||||
|
this.callbacksCapabilities[callbackId] = capability;
|
||||||
|
try {
|
||||||
|
this.postMessage(message, transfers);
|
||||||
|
} catch (e) {
|
||||||
|
capability.reject(e);
|
||||||
|
}
|
||||||
|
return capability.promise;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Sends a message to the comObj to invoke the action with the supplied data.
|
||||||
|
* Expect that the other side will callback to signal 'start_complete'.
|
||||||
|
* @param {String} actionName - Action to call.
|
||||||
|
* @param {JSON} data - JSON data to send.
|
||||||
|
* @param {Object} queueingStrategy - strategy to signal backpressure based on
|
||||||
|
* internal queue.
|
||||||
|
* @param {Array} [transfers] - Optional list of transfers/ArrayBuffers.
|
||||||
|
* @return {ReadableStream} ReadableStream to read data in chunks.
|
||||||
|
*/
|
||||||
|
sendWithStream(actionName, data, queueingStrategy, transfers) {
|
||||||
|
let streamId = this.streamId++;
|
||||||
|
let sourceName = this.sourceName;
|
||||||
|
let targetName = this.targetName;
|
||||||
|
|
||||||
|
return new ReadableStream({
|
||||||
|
start: (controller) => {
|
||||||
|
let startCapability = createPromiseCapability();
|
||||||
|
this.streamControllers[streamId] = {
|
||||||
|
controller,
|
||||||
|
startCall: startCapability,
|
||||||
|
isClosed: false,
|
||||||
|
};
|
||||||
|
this.postMessage({
|
||||||
|
sourceName,
|
||||||
|
targetName,
|
||||||
|
action: actionName,
|
||||||
|
streamId,
|
||||||
|
data,
|
||||||
|
desiredSize: controller.desiredSize,
|
||||||
|
});
|
||||||
|
// Return Promise for Async process, to signal success/failure.
|
||||||
|
return startCapability.promise;
|
||||||
|
},
|
||||||
|
|
||||||
|
pull: (controller) => {
|
||||||
|
let pullCapability = createPromiseCapability();
|
||||||
|
this.streamControllers[streamId].pullCall = pullCapability;
|
||||||
|
this.postMessage({
|
||||||
|
sourceName,
|
||||||
|
targetName,
|
||||||
|
stream: 'pull',
|
||||||
|
streamId,
|
||||||
|
desiredSize: controller.desiredSize,
|
||||||
|
});
|
||||||
|
// Returning Promise will not call "pull"
|
||||||
|
// again until current pull is resolved.
|
||||||
|
return pullCapability.promise;
|
||||||
|
},
|
||||||
|
|
||||||
|
cancel: (reason) => {
|
||||||
|
let cancelCapability = createPromiseCapability();
|
||||||
|
this.streamControllers[streamId].cancelCall = cancelCapability;
|
||||||
|
this.streamControllers[streamId].isClosed = true;
|
||||||
|
this.postMessage({
|
||||||
|
sourceName,
|
||||||
|
targetName,
|
||||||
|
stream: 'cancel',
|
||||||
|
reason,
|
||||||
|
streamId,
|
||||||
|
});
|
||||||
|
// Return Promise to signal success or failure.
|
||||||
|
return cancelCapability.promise;
|
||||||
|
},
|
||||||
|
}, queueingStrategy);
|
||||||
|
},
|
||||||
|
|
||||||
|
_createStreamSink(data) {
|
||||||
|
let self = this;
|
||||||
|
let action = this.actionHandler[data.action];
|
||||||
|
let streamId = data.streamId;
|
||||||
|
let desiredSize = data.desiredSize;
|
||||||
|
let sourceName = this.sourceName;
|
||||||
|
let targetName = data.sourceName;
|
||||||
|
let capability = createPromiseCapability();
|
||||||
|
|
||||||
|
let sendStreamRequest = ({ stream, chunk, transfers,
|
||||||
|
success, reason, }) => {
|
||||||
|
this.postMessage({ sourceName, targetName, stream, streamId,
|
||||||
|
chunk, success, reason, }, transfers);
|
||||||
|
};
|
||||||
|
|
||||||
|
let streamSink = {
|
||||||
|
enqueue(chunk, size = 1, transfers) {
|
||||||
|
if (this.isCancelled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let lastDesiredSize = this.desiredSize;
|
||||||
|
this.desiredSize -= size;
|
||||||
|
// Enqueue decreases the desiredSize property of sink,
|
||||||
|
// so when it changes from positive to negative,
|
||||||
|
// set ready as unresolved promise.
|
||||||
|
if (lastDesiredSize > 0 && this.desiredSize <= 0) {
|
||||||
|
this.sinkCapability = createPromiseCapability();
|
||||||
|
this.ready = this.sinkCapability.promise;
|
||||||
|
}
|
||||||
|
sendStreamRequest({ stream: 'enqueue', chunk, transfers, });
|
||||||
|
},
|
||||||
|
|
||||||
|
close() {
|
||||||
|
if (this.isCancelled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isCancelled = true;
|
||||||
|
sendStreamRequest({ stream: 'close', });
|
||||||
|
delete self.streamSinks[streamId];
|
||||||
|
},
|
||||||
|
|
||||||
|
error(reason) {
|
||||||
|
if (this.isCancelled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isCancelled = true;
|
||||||
|
sendStreamRequest({ stream: 'error', reason, });
|
||||||
|
},
|
||||||
|
|
||||||
|
sinkCapability: capability,
|
||||||
|
onPull: null,
|
||||||
|
onCancel: null,
|
||||||
|
isCancelled: false,
|
||||||
|
desiredSize,
|
||||||
|
ready: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
streamSink.sinkCapability.resolve();
|
||||||
|
streamSink.ready = streamSink.sinkCapability.promise;
|
||||||
|
this.streamSinks[streamId] = streamSink;
|
||||||
|
resolveCall(action[0], [data.data, streamSink], action[1]).then(() => {
|
||||||
|
sendStreamRequest({ stream: 'start_complete', success: true, });
|
||||||
|
}, (reason) => {
|
||||||
|
sendStreamRequest({ stream: 'start_complete', success: false, reason, });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_processStreamMessage(data) {
|
||||||
|
let sourceName = this.sourceName;
|
||||||
|
let targetName = data.sourceName;
|
||||||
|
let streamId = data.streamId;
|
||||||
|
|
||||||
|
let sendStreamResponse = ({ stream, success, reason, }) => {
|
||||||
|
this.comObj.postMessage({ sourceName, targetName, stream,
|
||||||
|
success, streamId, reason, });
|
||||||
|
};
|
||||||
|
|
||||||
|
let deleteStreamController = () => {
|
||||||
|
// Delete streamController only when start, pull and
|
||||||
|
// cancel callbacks are resolved, to avoid "TypeError".
|
||||||
|
Promise.all([
|
||||||
|
this.streamControllers[data.streamId].startCall,
|
||||||
|
this.streamControllers[data.streamId].pullCall,
|
||||||
|
this.streamControllers[data.streamId].cancelCall
|
||||||
|
].map(function(capability) {
|
||||||
|
return capability && finalize(capability.promise);
|
||||||
|
})).then(() => {
|
||||||
|
delete this.streamControllers[data.streamId];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (data.stream) {
|
||||||
|
case 'start_complete':
|
||||||
|
resolveOrReject(this.streamControllers[data.streamId].startCall,
|
||||||
|
data.success, wrapReason(data.reason));
|
||||||
|
break;
|
||||||
|
case 'pull_complete':
|
||||||
|
resolveOrReject(this.streamControllers[data.streamId].pullCall,
|
||||||
|
data.success, wrapReason(data.reason));
|
||||||
|
break;
|
||||||
|
case 'pull':
|
||||||
|
// Ignore any pull after close is called.
|
||||||
|
if (!this.streamSinks[data.streamId]) {
|
||||||
|
sendStreamResponse({ stream: 'pull_complete', success: true, });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Pull increases the desiredSize property of sink,
|
||||||
|
// so when it changes from negative to positive,
|
||||||
|
// set ready property as resolved promise.
|
||||||
|
if (this.streamSinks[data.streamId].desiredSize <= 0 &&
|
||||||
|
data.desiredSize > 0) {
|
||||||
|
this.streamSinks[data.streamId].sinkCapability.resolve();
|
||||||
|
}
|
||||||
|
// Reset desiredSize property of sink on every pull.
|
||||||
|
this.streamSinks[data.streamId].desiredSize = data.desiredSize;
|
||||||
|
resolveCall(this.streamSinks[data.streamId].onPull).then(() => {
|
||||||
|
sendStreamResponse({ stream: 'pull_complete', success: true, });
|
||||||
|
}, (reason) => {
|
||||||
|
sendStreamResponse({ stream: 'pull_complete',
|
||||||
|
success: false, reason, });
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'enqueue':
|
||||||
|
assert(this.streamControllers[data.streamId],
|
||||||
|
'enqueue should have stream controller');
|
||||||
|
if (!this.streamControllers[data.streamId].isClosed) {
|
||||||
|
this.streamControllers[data.streamId].controller.enqueue(data.chunk);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'close':
|
||||||
|
assert(this.streamControllers[data.streamId],
|
||||||
|
'close should have stream controller');
|
||||||
|
if (this.streamControllers[data.streamId].isClosed) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.streamControllers[data.streamId].isClosed = true;
|
||||||
|
this.streamControllers[data.streamId].controller.close();
|
||||||
|
deleteStreamController();
|
||||||
|
break;
|
||||||
|
case 'error':
|
||||||
|
assert(this.streamControllers[data.streamId],
|
||||||
|
'error should have stream controller');
|
||||||
|
this.streamControllers[data.streamId].controller.
|
||||||
|
error(wrapReason(data.reason));
|
||||||
|
deleteStreamController();
|
||||||
|
break;
|
||||||
|
case 'cancel_complete':
|
||||||
|
resolveOrReject(this.streamControllers[data.streamId].cancelCall,
|
||||||
|
data.success, wrapReason(data.reason));
|
||||||
|
deleteStreamController();
|
||||||
|
break;
|
||||||
|
case 'cancel':
|
||||||
|
if (!this.streamSinks[data.streamId]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
resolveCall(this.streamSinks[data.streamId].onCancel,
|
||||||
|
[wrapReason(data.reason)]).then(() => {
|
||||||
|
sendStreamResponse({ stream: 'cancel_complete', success: true, });
|
||||||
|
}, (reason) => {
|
||||||
|
sendStreamResponse({ stream: 'cancel_complete',
|
||||||
|
success: false, reason, });
|
||||||
|
});
|
||||||
|
this.streamSinks[data.streamId].sinkCapability.
|
||||||
|
reject(wrapReason(data.reason));
|
||||||
|
this.streamSinks[data.streamId].isCancelled = true;
|
||||||
|
delete this.streamSinks[data.streamId];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('Unexpected stream case');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends raw message to the comObj.
|
||||||
|
* @private
|
||||||
|
* @param {Object} message - Raw message.
|
||||||
|
* @param transfers List of transfers/ArrayBuffers, or undefined.
|
||||||
|
*/
|
||||||
|
postMessage(message, transfers) {
|
||||||
|
if (transfers && this.postMessageTransfers) {
|
||||||
|
this.comObj.postMessage(message, transfers);
|
||||||
|
} else {
|
||||||
|
this.comObj.postMessage(message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.comObj.removeEventListener('message', this._onComObjOnMessage);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
MessageHandler,
|
||||||
|
};
|
@ -926,142 +926,6 @@ var Util = (function UtilClosure() {
|
|||||||
return Util;
|
return Util;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/**
|
|
||||||
* PDF page viewport created based on scale, rotation and offset.
|
|
||||||
* @class
|
|
||||||
* @alias PageViewport
|
|
||||||
*/
|
|
||||||
var PageViewport = (function PageViewportClosure() {
|
|
||||||
/**
|
|
||||||
* @constructor
|
|
||||||
* @private
|
|
||||||
* @param viewBox {Array} xMin, yMin, xMax and yMax coordinates.
|
|
||||||
* @param scale {number} scale of the viewport.
|
|
||||||
* @param rotation {number} rotations of the viewport in degrees.
|
|
||||||
* @param offsetX {number} offset X
|
|
||||||
* @param offsetY {number} offset Y
|
|
||||||
* @param dontFlip {boolean} if true, axis Y will not be flipped.
|
|
||||||
*/
|
|
||||||
function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
|
|
||||||
this.viewBox = viewBox;
|
|
||||||
this.scale = scale;
|
|
||||||
this.rotation = rotation;
|
|
||||||
this.offsetX = offsetX;
|
|
||||||
this.offsetY = offsetY;
|
|
||||||
|
|
||||||
// creating transform to convert pdf coordinate system to the normal
|
|
||||||
// canvas like coordinates taking in account scale and rotation
|
|
||||||
var centerX = (viewBox[2] + viewBox[0]) / 2;
|
|
||||||
var centerY = (viewBox[3] + viewBox[1]) / 2;
|
|
||||||
var rotateA, rotateB, rotateC, rotateD;
|
|
||||||
rotation = rotation % 360;
|
|
||||||
rotation = rotation < 0 ? rotation + 360 : rotation;
|
|
||||||
switch (rotation) {
|
|
||||||
case 180:
|
|
||||||
rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
|
|
||||||
break;
|
|
||||||
case 90:
|
|
||||||
rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
|
|
||||||
break;
|
|
||||||
case 270:
|
|
||||||
rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
|
|
||||||
break;
|
|
||||||
// case 0:
|
|
||||||
default:
|
|
||||||
rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dontFlip) {
|
|
||||||
rotateC = -rotateC; rotateD = -rotateD;
|
|
||||||
}
|
|
||||||
|
|
||||||
var offsetCanvasX, offsetCanvasY;
|
|
||||||
var width, height;
|
|
||||||
if (rotateA === 0) {
|
|
||||||
offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
|
|
||||||
offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
|
|
||||||
width = Math.abs(viewBox[3] - viewBox[1]) * scale;
|
|
||||||
height = Math.abs(viewBox[2] - viewBox[0]) * scale;
|
|
||||||
} else {
|
|
||||||
offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
|
|
||||||
offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
|
|
||||||
width = Math.abs(viewBox[2] - viewBox[0]) * scale;
|
|
||||||
height = Math.abs(viewBox[3] - viewBox[1]) * scale;
|
|
||||||
}
|
|
||||||
// creating transform for the following operations:
|
|
||||||
// translate(-centerX, -centerY), rotate and flip vertically,
|
|
||||||
// scale, and translate(offsetCanvasX, offsetCanvasY)
|
|
||||||
this.transform = [
|
|
||||||
rotateA * scale,
|
|
||||||
rotateB * scale,
|
|
||||||
rotateC * scale,
|
|
||||||
rotateD * scale,
|
|
||||||
offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
|
|
||||||
offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
|
|
||||||
];
|
|
||||||
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.fontScale = scale;
|
|
||||||
}
|
|
||||||
PageViewport.prototype = /** @lends PageViewport.prototype */ {
|
|
||||||
/**
|
|
||||||
* Clones viewport with additional properties.
|
|
||||||
* @param args {Object} (optional) If specified, may contain the 'scale' or
|
|
||||||
* 'rotation' properties to override the corresponding properties in
|
|
||||||
* the cloned viewport.
|
|
||||||
* @returns {PageViewport} Cloned viewport.
|
|
||||||
*/
|
|
||||||
clone: function PageViewPort_clone(args) {
|
|
||||||
args = args || {};
|
|
||||||
var scale = 'scale' in args ? args.scale : this.scale;
|
|
||||||
var rotation = 'rotation' in args ? args.rotation : this.rotation;
|
|
||||||
return new PageViewport(this.viewBox.slice(), scale, rotation,
|
|
||||||
this.offsetX, this.offsetY, args.dontFlip);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Converts PDF point to the viewport coordinates. For examples, useful for
|
|
||||||
* converting PDF location into canvas pixel coordinates.
|
|
||||||
* @param x {number} X coordinate.
|
|
||||||
* @param y {number} Y coordinate.
|
|
||||||
* @returns {Object} Object that contains 'x' and 'y' properties of the
|
|
||||||
* point in the viewport coordinate space.
|
|
||||||
* @see {@link convertToPdfPoint}
|
|
||||||
* @see {@link convertToViewportRectangle}
|
|
||||||
*/
|
|
||||||
convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
|
|
||||||
return Util.applyTransform([x, y], this.transform);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Converts PDF rectangle to the viewport coordinates.
|
|
||||||
* @param rect {Array} xMin, yMin, xMax and yMax coordinates.
|
|
||||||
* @returns {Array} Contains corresponding coordinates of the rectangle
|
|
||||||
* in the viewport coordinate space.
|
|
||||||
* @see {@link convertToViewportPoint}
|
|
||||||
*/
|
|
||||||
convertToViewportRectangle:
|
|
||||||
function PageViewport_convertToViewportRectangle(rect) {
|
|
||||||
var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
|
|
||||||
var br = Util.applyTransform([rect[2], rect[3]], this.transform);
|
|
||||||
return [tl[0], tl[1], br[0], br[1]];
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Converts viewport coordinates to the PDF location. For examples, useful
|
|
||||||
* for converting canvas pixel location into PDF one.
|
|
||||||
* @param x {number} X coordinate.
|
|
||||||
* @param y {number} Y coordinate.
|
|
||||||
* @returns {Object} Object that contains 'x' and 'y' properties of the
|
|
||||||
* point in the PDF coordinate space.
|
|
||||||
* @see {@link convertToViewportPoint}
|
|
||||||
*/
|
|
||||||
convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
|
|
||||||
return Util.applyInverseTransform([x, y], this.transform);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return PageViewport;
|
|
||||||
})();
|
|
||||||
|
|
||||||
var PDFStringTranslateTable = [
|
var PDFStringTranslateTable = [
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
|
0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
|
||||||
@ -1184,429 +1048,6 @@ var createObjectURL = (function createObjectURLClosure() {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function resolveCall(fn, args, thisArg = null) {
|
|
||||||
if (!fn) {
|
|
||||||
return Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
resolve(fn.apply(thisArg, args));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function wrapReason(reason) {
|
|
||||||
if (typeof reason !== 'object') {
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
switch (reason.name) {
|
|
||||||
case 'AbortException':
|
|
||||||
return new AbortException(reason.message);
|
|
||||||
case 'MissingPDFException':
|
|
||||||
return new MissingPDFException(reason.message);
|
|
||||||
case 'UnexpectedResponseException':
|
|
||||||
return new UnexpectedResponseException(reason.message, reason.status);
|
|
||||||
default:
|
|
||||||
return new UnknownErrorException(reason.message, reason.details);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeReasonSerializable(reason) {
|
|
||||||
if (!(reason instanceof Error) ||
|
|
||||||
reason instanceof AbortException ||
|
|
||||||
reason instanceof MissingPDFException ||
|
|
||||||
reason instanceof UnexpectedResponseException ||
|
|
||||||
reason instanceof UnknownErrorException) {
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
return new UnknownErrorException(reason.message, reason.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveOrReject(capability, success, reason) {
|
|
||||||
if (success) {
|
|
||||||
capability.resolve();
|
|
||||||
} else {
|
|
||||||
capability.reject(reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function finalize(promise) {
|
|
||||||
return Promise.resolve(promise).catch(() => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function MessageHandler(sourceName, targetName, comObj) {
|
|
||||||
this.sourceName = sourceName;
|
|
||||||
this.targetName = targetName;
|
|
||||||
this.comObj = comObj;
|
|
||||||
this.callbackId = 1;
|
|
||||||
this.streamId = 1;
|
|
||||||
this.postMessageTransfers = true;
|
|
||||||
this.streamSinks = Object.create(null);
|
|
||||||
this.streamControllers = Object.create(null);
|
|
||||||
let callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
|
|
||||||
let ah = this.actionHandler = Object.create(null);
|
|
||||||
|
|
||||||
this._onComObjOnMessage = (event) => {
|
|
||||||
let data = event.data;
|
|
||||||
if (data.targetName !== this.sourceName) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (data.stream) {
|
|
||||||
this._processStreamMessage(data);
|
|
||||||
} else if (data.isReply) {
|
|
||||||
let callbackId = data.callbackId;
|
|
||||||
if (data.callbackId in callbacksCapabilities) {
|
|
||||||
let callback = callbacksCapabilities[callbackId];
|
|
||||||
delete callbacksCapabilities[callbackId];
|
|
||||||
if ('error' in data) {
|
|
||||||
callback.reject(wrapReason(data.error));
|
|
||||||
} else {
|
|
||||||
callback.resolve(data.data);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error(`Cannot resolve callback ${callbackId}`);
|
|
||||||
}
|
|
||||||
} else if (data.action in ah) {
|
|
||||||
let action = ah[data.action];
|
|
||||||
if (data.callbackId) {
|
|
||||||
let sourceName = this.sourceName;
|
|
||||||
let targetName = data.sourceName;
|
|
||||||
Promise.resolve().then(function () {
|
|
||||||
return action[0].call(action[1], data.data);
|
|
||||||
}).then((result) => {
|
|
||||||
comObj.postMessage({
|
|
||||||
sourceName,
|
|
||||||
targetName,
|
|
||||||
isReply: true,
|
|
||||||
callbackId: data.callbackId,
|
|
||||||
data: result,
|
|
||||||
});
|
|
||||||
}, (reason) => {
|
|
||||||
comObj.postMessage({
|
|
||||||
sourceName,
|
|
||||||
targetName,
|
|
||||||
isReply: true,
|
|
||||||
callbackId: data.callbackId,
|
|
||||||
error: makeReasonSerializable(reason),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else if (data.streamId) {
|
|
||||||
this._createStreamSink(data);
|
|
||||||
} else {
|
|
||||||
action[0].call(action[1], data.data);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error(`Unknown action from worker: ${data.action}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
comObj.addEventListener('message', this._onComObjOnMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageHandler.prototype = {
|
|
||||||
on(actionName, handler, scope) {
|
|
||||||
var ah = this.actionHandler;
|
|
||||||
if (ah[actionName]) {
|
|
||||||
throw new Error(`There is already an actionName called "${actionName}"`);
|
|
||||||
}
|
|
||||||
ah[actionName] = [handler, scope];
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Sends a message to the comObj to invoke the action with the supplied data.
|
|
||||||
* @param {String} actionName - Action to call.
|
|
||||||
* @param {JSON} data - JSON data to send.
|
|
||||||
* @param {Array} [transfers] - Optional list of transfers/ArrayBuffers
|
|
||||||
*/
|
|
||||||
send(actionName, data, transfers) {
|
|
||||||
var message = {
|
|
||||||
sourceName: this.sourceName,
|
|
||||||
targetName: this.targetName,
|
|
||||||
action: actionName,
|
|
||||||
data,
|
|
||||||
};
|
|
||||||
this.postMessage(message, transfers);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Sends a message to the comObj to invoke the action with the supplied data.
|
|
||||||
* Expects that the other side will callback with the response.
|
|
||||||
* @param {String} actionName - Action to call.
|
|
||||||
* @param {JSON} data - JSON data to send.
|
|
||||||
* @param {Array} [transfers] - Optional list of transfers/ArrayBuffers.
|
|
||||||
* @returns {Promise} Promise to be resolved with response data.
|
|
||||||
*/
|
|
||||||
sendWithPromise(actionName, data, transfers) {
|
|
||||||
var callbackId = this.callbackId++;
|
|
||||||
var message = {
|
|
||||||
sourceName: this.sourceName,
|
|
||||||
targetName: this.targetName,
|
|
||||||
action: actionName,
|
|
||||||
data,
|
|
||||||
callbackId,
|
|
||||||
};
|
|
||||||
var capability = createPromiseCapability();
|
|
||||||
this.callbacksCapabilities[callbackId] = capability;
|
|
||||||
try {
|
|
||||||
this.postMessage(message, transfers);
|
|
||||||
} catch (e) {
|
|
||||||
capability.reject(e);
|
|
||||||
}
|
|
||||||
return capability.promise;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Sends a message to the comObj to invoke the action with the supplied data.
|
|
||||||
* Expect that the other side will callback to signal 'start_complete'.
|
|
||||||
* @param {String} actionName - Action to call.
|
|
||||||
* @param {JSON} data - JSON data to send.
|
|
||||||
* @param {Object} queueingStrategy - strategy to signal backpressure based on
|
|
||||||
* internal queue.
|
|
||||||
* @param {Array} [transfers] - Optional list of transfers/ArrayBuffers.
|
|
||||||
* @return {ReadableStream} ReadableStream to read data in chunks.
|
|
||||||
*/
|
|
||||||
sendWithStream(actionName, data, queueingStrategy, transfers) {
|
|
||||||
let streamId = this.streamId++;
|
|
||||||
let sourceName = this.sourceName;
|
|
||||||
let targetName = this.targetName;
|
|
||||||
|
|
||||||
return new ReadableStream({
|
|
||||||
start: (controller) => {
|
|
||||||
let startCapability = createPromiseCapability();
|
|
||||||
this.streamControllers[streamId] = {
|
|
||||||
controller,
|
|
||||||
startCall: startCapability,
|
|
||||||
isClosed: false,
|
|
||||||
};
|
|
||||||
this.postMessage({
|
|
||||||
sourceName,
|
|
||||||
targetName,
|
|
||||||
action: actionName,
|
|
||||||
streamId,
|
|
||||||
data,
|
|
||||||
desiredSize: controller.desiredSize,
|
|
||||||
});
|
|
||||||
// Return Promise for Async process, to signal success/failure.
|
|
||||||
return startCapability.promise;
|
|
||||||
},
|
|
||||||
|
|
||||||
pull: (controller) => {
|
|
||||||
let pullCapability = createPromiseCapability();
|
|
||||||
this.streamControllers[streamId].pullCall = pullCapability;
|
|
||||||
this.postMessage({
|
|
||||||
sourceName,
|
|
||||||
targetName,
|
|
||||||
stream: 'pull',
|
|
||||||
streamId,
|
|
||||||
desiredSize: controller.desiredSize,
|
|
||||||
});
|
|
||||||
// Returning Promise will not call "pull"
|
|
||||||
// again until current pull is resolved.
|
|
||||||
return pullCapability.promise;
|
|
||||||
},
|
|
||||||
|
|
||||||
cancel: (reason) => {
|
|
||||||
let cancelCapability = createPromiseCapability();
|
|
||||||
this.streamControllers[streamId].cancelCall = cancelCapability;
|
|
||||||
this.streamControllers[streamId].isClosed = true;
|
|
||||||
this.postMessage({
|
|
||||||
sourceName,
|
|
||||||
targetName,
|
|
||||||
stream: 'cancel',
|
|
||||||
reason,
|
|
||||||
streamId,
|
|
||||||
});
|
|
||||||
// Return Promise to signal success or failure.
|
|
||||||
return cancelCapability.promise;
|
|
||||||
},
|
|
||||||
}, queueingStrategy);
|
|
||||||
},
|
|
||||||
|
|
||||||
_createStreamSink(data) {
|
|
||||||
let self = this;
|
|
||||||
let action = this.actionHandler[data.action];
|
|
||||||
let streamId = data.streamId;
|
|
||||||
let desiredSize = data.desiredSize;
|
|
||||||
let sourceName = this.sourceName;
|
|
||||||
let targetName = data.sourceName;
|
|
||||||
let capability = createPromiseCapability();
|
|
||||||
|
|
||||||
let sendStreamRequest = ({ stream, chunk, transfers,
|
|
||||||
success, reason, }) => {
|
|
||||||
this.postMessage({ sourceName, targetName, stream, streamId,
|
|
||||||
chunk, success, reason, }, transfers);
|
|
||||||
};
|
|
||||||
|
|
||||||
let streamSink = {
|
|
||||||
enqueue(chunk, size = 1, transfers) {
|
|
||||||
if (this.isCancelled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let lastDesiredSize = this.desiredSize;
|
|
||||||
this.desiredSize -= size;
|
|
||||||
// Enqueue decreases the desiredSize property of sink,
|
|
||||||
// so when it changes from positive to negative,
|
|
||||||
// set ready as unresolved promise.
|
|
||||||
if (lastDesiredSize > 0 && this.desiredSize <= 0) {
|
|
||||||
this.sinkCapability = createPromiseCapability();
|
|
||||||
this.ready = this.sinkCapability.promise;
|
|
||||||
}
|
|
||||||
sendStreamRequest({ stream: 'enqueue', chunk, transfers, });
|
|
||||||
},
|
|
||||||
|
|
||||||
close() {
|
|
||||||
if (this.isCancelled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.isCancelled = true;
|
|
||||||
sendStreamRequest({ stream: 'close', });
|
|
||||||
delete self.streamSinks[streamId];
|
|
||||||
},
|
|
||||||
|
|
||||||
error(reason) {
|
|
||||||
if (this.isCancelled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.isCancelled = true;
|
|
||||||
sendStreamRequest({ stream: 'error', reason, });
|
|
||||||
},
|
|
||||||
|
|
||||||
sinkCapability: capability,
|
|
||||||
onPull: null,
|
|
||||||
onCancel: null,
|
|
||||||
isCancelled: false,
|
|
||||||
desiredSize,
|
|
||||||
ready: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
streamSink.sinkCapability.resolve();
|
|
||||||
streamSink.ready = streamSink.sinkCapability.promise;
|
|
||||||
this.streamSinks[streamId] = streamSink;
|
|
||||||
resolveCall(action[0], [data.data, streamSink], action[1]).then(() => {
|
|
||||||
sendStreamRequest({ stream: 'start_complete', success: true, });
|
|
||||||
}, (reason) => {
|
|
||||||
sendStreamRequest({ stream: 'start_complete', success: false, reason, });
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_processStreamMessage(data) {
|
|
||||||
let sourceName = this.sourceName;
|
|
||||||
let targetName = data.sourceName;
|
|
||||||
let streamId = data.streamId;
|
|
||||||
|
|
||||||
let sendStreamResponse = ({ stream, success, reason, }) => {
|
|
||||||
this.comObj.postMessage({ sourceName, targetName, stream,
|
|
||||||
success, streamId, reason, });
|
|
||||||
};
|
|
||||||
|
|
||||||
let deleteStreamController = () => {
|
|
||||||
// Delete streamController only when start, pull and
|
|
||||||
// cancel callbacks are resolved, to avoid "TypeError".
|
|
||||||
Promise.all([
|
|
||||||
this.streamControllers[data.streamId].startCall,
|
|
||||||
this.streamControllers[data.streamId].pullCall,
|
|
||||||
this.streamControllers[data.streamId].cancelCall
|
|
||||||
].map(function(capability) {
|
|
||||||
return capability && finalize(capability.promise);
|
|
||||||
})).then(() => {
|
|
||||||
delete this.streamControllers[data.streamId];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (data.stream) {
|
|
||||||
case 'start_complete':
|
|
||||||
resolveOrReject(this.streamControllers[data.streamId].startCall,
|
|
||||||
data.success, wrapReason(data.reason));
|
|
||||||
break;
|
|
||||||
case 'pull_complete':
|
|
||||||
resolveOrReject(this.streamControllers[data.streamId].pullCall,
|
|
||||||
data.success, wrapReason(data.reason));
|
|
||||||
break;
|
|
||||||
case 'pull':
|
|
||||||
// Ignore any pull after close is called.
|
|
||||||
if (!this.streamSinks[data.streamId]) {
|
|
||||||
sendStreamResponse({ stream: 'pull_complete', success: true, });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Pull increases the desiredSize property of sink,
|
|
||||||
// so when it changes from negative to positive,
|
|
||||||
// set ready property as resolved promise.
|
|
||||||
if (this.streamSinks[data.streamId].desiredSize <= 0 &&
|
|
||||||
data.desiredSize > 0) {
|
|
||||||
this.streamSinks[data.streamId].sinkCapability.resolve();
|
|
||||||
}
|
|
||||||
// Reset desiredSize property of sink on every pull.
|
|
||||||
this.streamSinks[data.streamId].desiredSize = data.desiredSize;
|
|
||||||
resolveCall(this.streamSinks[data.streamId].onPull).then(() => {
|
|
||||||
sendStreamResponse({ stream: 'pull_complete', success: true, });
|
|
||||||
}, (reason) => {
|
|
||||||
sendStreamResponse({ stream: 'pull_complete',
|
|
||||||
success: false, reason, });
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'enqueue':
|
|
||||||
assert(this.streamControllers[data.streamId],
|
|
||||||
'enqueue should have stream controller');
|
|
||||||
if (!this.streamControllers[data.streamId].isClosed) {
|
|
||||||
this.streamControllers[data.streamId].controller.enqueue(data.chunk);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'close':
|
|
||||||
assert(this.streamControllers[data.streamId],
|
|
||||||
'close should have stream controller');
|
|
||||||
if (this.streamControllers[data.streamId].isClosed) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.streamControllers[data.streamId].isClosed = true;
|
|
||||||
this.streamControllers[data.streamId].controller.close();
|
|
||||||
deleteStreamController();
|
|
||||||
break;
|
|
||||||
case 'error':
|
|
||||||
assert(this.streamControllers[data.streamId],
|
|
||||||
'error should have stream controller');
|
|
||||||
this.streamControllers[data.streamId].controller.
|
|
||||||
error(wrapReason(data.reason));
|
|
||||||
deleteStreamController();
|
|
||||||
break;
|
|
||||||
case 'cancel_complete':
|
|
||||||
resolveOrReject(this.streamControllers[data.streamId].cancelCall,
|
|
||||||
data.success, wrapReason(data.reason));
|
|
||||||
deleteStreamController();
|
|
||||||
break;
|
|
||||||
case 'cancel':
|
|
||||||
if (!this.streamSinks[data.streamId]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
resolveCall(this.streamSinks[data.streamId].onCancel,
|
|
||||||
[wrapReason(data.reason)]).then(() => {
|
|
||||||
sendStreamResponse({ stream: 'cancel_complete', success: true, });
|
|
||||||
}, (reason) => {
|
|
||||||
sendStreamResponse({ stream: 'cancel_complete',
|
|
||||||
success: false, reason, });
|
|
||||||
});
|
|
||||||
this.streamSinks[data.streamId].sinkCapability.
|
|
||||||
reject(wrapReason(data.reason));
|
|
||||||
this.streamSinks[data.streamId].isCancelled = true;
|
|
||||||
delete this.streamSinks[data.streamId];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error('Unexpected stream case');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends raw message to the comObj.
|
|
||||||
* @private
|
|
||||||
* @param {Object} message - Raw message.
|
|
||||||
* @param transfers List of transfers/ArrayBuffers, or undefined.
|
|
||||||
*/
|
|
||||||
postMessage(message, transfers) {
|
|
||||||
if (transfers && this.postMessageTransfers) {
|
|
||||||
this.comObj.postMessage(message, transfers);
|
|
||||||
} else {
|
|
||||||
this.comObj.postMessage(message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy() {
|
|
||||||
this.comObj.removeEventListener('message', this._onComObjOnMessage);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
FONT_IDENTITY_MATRIX,
|
FONT_IDENTITY_MATRIX,
|
||||||
IDENTITY_MATRIX,
|
IDENTITY_MATRIX,
|
||||||
@ -1622,12 +1063,10 @@ export {
|
|||||||
CMapCompressionType,
|
CMapCompressionType,
|
||||||
AbortException,
|
AbortException,
|
||||||
InvalidPDFException,
|
InvalidPDFException,
|
||||||
MessageHandler,
|
|
||||||
MissingDataException,
|
MissingDataException,
|
||||||
MissingPDFException,
|
MissingPDFException,
|
||||||
NativeImageDecoding,
|
NativeImageDecoding,
|
||||||
NotImplementedException,
|
NotImplementedException,
|
||||||
PageViewport,
|
|
||||||
PasswordException,
|
PasswordException,
|
||||||
PasswordResponses,
|
PasswordResponses,
|
||||||
StreamType,
|
StreamType,
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"evaluator_spec.js",
|
"evaluator_spec.js",
|
||||||
"fonts_spec.js",
|
"fonts_spec.js",
|
||||||
"function_spec.js",
|
"function_spec.js",
|
||||||
|
"message_handler_spec.js",
|
||||||
"metadata_spec.js",
|
"metadata_spec.js",
|
||||||
"murmurhash3_spec.js",
|
"murmurhash3_spec.js",
|
||||||
"network_utils_spec.js",
|
"network_utils_spec.js",
|
||||||
@ -31,7 +32,6 @@
|
|||||||
"type1_parser_spec.js",
|
"type1_parser_spec.js",
|
||||||
"ui_utils_spec.js",
|
"ui_utils_spec.js",
|
||||||
"unicode_spec.js",
|
"unicode_spec.js",
|
||||||
"util_spec.js",
|
"util_spec.js"
|
||||||
"util_stream_spec.js"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@ function initializePDFJS(callback) {
|
|||||||
'pdfjs-test/unit/evaluator_spec',
|
'pdfjs-test/unit/evaluator_spec',
|
||||||
'pdfjs-test/unit/fonts_spec',
|
'pdfjs-test/unit/fonts_spec',
|
||||||
'pdfjs-test/unit/function_spec',
|
'pdfjs-test/unit/function_spec',
|
||||||
|
'pdfjs-test/unit/message_handler_spec',
|
||||||
'pdfjs-test/unit/metadata_spec',
|
'pdfjs-test/unit/metadata_spec',
|
||||||
'pdfjs-test/unit/murmurhash3_spec',
|
'pdfjs-test/unit/murmurhash3_spec',
|
||||||
'pdfjs-test/unit/network_spec',
|
'pdfjs-test/unit/network_spec',
|
||||||
@ -74,7 +75,6 @@ function initializePDFJS(callback) {
|
|||||||
'pdfjs-test/unit/ui_utils_spec',
|
'pdfjs-test/unit/ui_utils_spec',
|
||||||
'pdfjs-test/unit/unicode_spec',
|
'pdfjs-test/unit/unicode_spec',
|
||||||
'pdfjs-test/unit/util_spec',
|
'pdfjs-test/unit/util_spec',
|
||||||
'pdfjs-test/unit/util_stream_spec',
|
|
||||||
].map(function (moduleName) {
|
].map(function (moduleName) {
|
||||||
return SystemJS.import(moduleName);
|
return SystemJS.import(moduleName);
|
||||||
})).then(function(modules) {
|
})).then(function(modules) {
|
||||||
|
@ -13,39 +13,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createPromiseCapability, MessageHandler } from '../../src/shared/util';
|
import { createPromiseCapability } from '../../src/shared/util';
|
||||||
|
import { LoopbackPort } from '../../src/display/api';
|
||||||
describe('util_stream', function () {
|
import { MessageHandler } from '../../src/shared/message_handler';
|
||||||
// Temporary fake port for sending messages between main and worker.
|
|
||||||
class FakePort {
|
|
||||||
constructor() {
|
|
||||||
this._listeners = [];
|
|
||||||
this._deferred = Promise.resolve(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
postMessage(obj) {
|
|
||||||
let event = { data: obj, };
|
|
||||||
this._deferred.then(() => {
|
|
||||||
this._listeners.forEach(function (listener) {
|
|
||||||
listener.call(this, event);
|
|
||||||
}, this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addEventListener(name, listener) {
|
|
||||||
this._listeners.push(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeEventListener(name, listener) {
|
|
||||||
let i = this._listeners.indexOf(listener);
|
|
||||||
this._listeners.splice(i, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
terminate() {
|
|
||||||
this._listeners = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
describe('message_handler', function () {
|
||||||
// Sleep function to wait for sometime, similar to setTimeout but faster.
|
// Sleep function to wait for sometime, similar to setTimeout but faster.
|
||||||
function sleep(ticks) {
|
function sleep(ticks) {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
@ -55,7 +27,7 @@ describe('util_stream', function () {
|
|||||||
|
|
||||||
describe('sendWithStream', function () {
|
describe('sendWithStream', function () {
|
||||||
it('should return a ReadableStream', function () {
|
it('should return a ReadableStream', function () {
|
||||||
let port = new FakePort();
|
let port = new LoopbackPort();
|
||||||
let messageHandler1 = new MessageHandler('main', 'worker', port);
|
let messageHandler1 = new MessageHandler('main', 'worker', port);
|
||||||
let readable = messageHandler1.sendWithStream('fakeHandler');
|
let readable = messageHandler1.sendWithStream('fakeHandler');
|
||||||
// Check if readable is an instance of ReadableStream.
|
// Check if readable is an instance of ReadableStream.
|
||||||
@ -65,7 +37,7 @@ describe('util_stream', function () {
|
|||||||
|
|
||||||
it('should read using a reader', function (done) {
|
it('should read using a reader', function (done) {
|
||||||
let log = '';
|
let log = '';
|
||||||
let port = new FakePort();
|
let port = new LoopbackPort();
|
||||||
let messageHandler1 = new MessageHandler('main', 'worker', port);
|
let messageHandler1 = new MessageHandler('main', 'worker', port);
|
||||||
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
||||||
messageHandler2.on('fakeHandler', (data, sink) => {
|
messageHandler2.on('fakeHandler', (data, sink) => {
|
||||||
@ -109,7 +81,7 @@ describe('util_stream', function () {
|
|||||||
|
|
||||||
it('should not read any data when cancelled', function (done) {
|
it('should not read any data when cancelled', function (done) {
|
||||||
let log = '';
|
let log = '';
|
||||||
let port = new FakePort();
|
let port = new LoopbackPort();
|
||||||
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
||||||
messageHandler2.on('fakeHandler', (data, sink) => {
|
messageHandler2.on('fakeHandler', (data, sink) => {
|
||||||
sink.onPull = function () {
|
sink.onPull = function () {
|
||||||
@ -161,7 +133,7 @@ describe('util_stream', function () {
|
|||||||
|
|
||||||
it('should not read when errored', function(done) {
|
it('should not read when errored', function(done) {
|
||||||
let log = '';
|
let log = '';
|
||||||
let port = new FakePort();
|
let port = new LoopbackPort();
|
||||||
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
||||||
messageHandler2.on('fakeHandler', (data, sink) => {
|
messageHandler2.on('fakeHandler', (data, sink) => {
|
||||||
sink.onPull = function () {
|
sink.onPull = function () {
|
||||||
@ -204,7 +176,7 @@ describe('util_stream', function () {
|
|||||||
|
|
||||||
it('should read data with blocking promise', function (done) {
|
it('should read data with blocking promise', function (done) {
|
||||||
let log = '';
|
let log = '';
|
||||||
let port = new FakePort();
|
let port = new LoopbackPort();
|
||||||
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
||||||
messageHandler2.on('fakeHandler', (data, sink) => {
|
messageHandler2.on('fakeHandler', (data, sink) => {
|
||||||
sink.onPull = function () {
|
sink.onPull = function () {
|
||||||
@ -265,7 +237,7 @@ describe('util_stream', function () {
|
|||||||
it('should read data with blocking promise and buffer whole data' +
|
it('should read data with blocking promise and buffer whole data' +
|
||||||
' into stream', function (done) {
|
' into stream', function (done) {
|
||||||
let log = '';
|
let log = '';
|
||||||
let port = new FakePort();
|
let port = new LoopbackPort();
|
||||||
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
||||||
messageHandler2.on('fakeHandler', (data, sink) => {
|
messageHandler2.on('fakeHandler', (data, sink) => {
|
||||||
sink.onPull = function () {
|
sink.onPull = function () {
|
||||||
@ -325,7 +297,7 @@ describe('util_stream', function () {
|
|||||||
|
|
||||||
it('should ignore any pull after close is called', function (done) {
|
it('should ignore any pull after close is called', function (done) {
|
||||||
let log = '';
|
let log = '';
|
||||||
let port = new FakePort();
|
let port = new LoopbackPort();
|
||||||
let capability = createPromiseCapability();
|
let capability = createPromiseCapability();
|
||||||
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
let messageHandler2 = new MessageHandler('worker', 'main', port);
|
||||||
messageHandler2.on('fakeHandler', (data, sink) => {
|
messageHandler2.on('fakeHandler', (data, sink) => {
|
Loading…
x
Reference in New Issue
Block a user