@vivliostyle/core
Version:
Vivliostyle Core library for HTML+CSS typesetting with EPUB/Web publications support
391 lines (390 loc) • 11 kB
TypeScript
/**
* Copyright 2013 Google, Inc.
* Copyright 2015 Trim-marks Inc.
* Copyright 2019 Vivliostyle Foundation
*
* Vivliostyle.js is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Vivliostyle.js is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Vivliostyle.js. If not, see <http://www.gnu.org/licenses/>.
*
* @fileoverview Task - Support for asynchronous execution and cooperative
* multitasking.
*/
import * as Base from "./base";
/**
* External timer. Only needed for testing.
*/
export interface Timer {
/**
* @return current time in milliseconds.
*/
currentTime(): number;
/**
* Calls function after a given timeout.
* @param fn function to call.
* @param delay timeout in milliseconds.
* @return unique number that can be used to clear the timeout.
*/
setTimeout(fn: () => void, delay: number): number;
/**
* Calls function after a given timeout.
* @param token timeout token.
* @return.
*/
clearTimeout(token: number): void;
}
/**
* Result of an asynchronous function that may be available immediately or
* some time later. Similar to Deferred.
* @template T
*/
export interface Result<T> {
/**
* Call the given function when asynchronous function is finished. Callback
* is executed in the task's context.
*/
then(callback: (p1: T) => void): void;
/**
* Call the given asynchronous function when some asynchronous function is
* finished. Callback is executed in the task's context.
* @template T1
*/
thenAsync<T1>(callback: (p1: T) => Result<T1>): Result<T1>;
/**
* Produce a Result that resolves to the given value when this Result is
* resolved.
* @template T1
*/
thenReturn<T1>(result: T1): Result<T1>;
/**
* Finish given frame with the result value when result becomes ready.
*/
thenFinish(frame: Frame<T>): void;
/**
* Check if this Result is still pending.
*/
isPending(): boolean;
/**
* If this Result is resolved, return the value that it holds.
*/
get(): T | null;
}
export declare let privateCurrentTask: Task | null;
export declare let primaryScheduler: Scheduler | null;
/**
* Returns current task.
*/
export declare function currentTask(): Task | null;
/**
* Create and return a new frame with the given name.
*/
export declare function newFrame<T>(name: string): Frame<T>;
export declare function newEventSource(): EventSource;
export declare function newScheduler(opt_timer?: Timer): Scheduler;
/**
* @template T
*/
export declare function newResult<T>(opt_value: T): Result<T>;
/**
* Creates a new frame and runs code in its context, catching synchronous and
* asynchronous errors. If an error occurs, onErr is run (in the context of
* the same frame). As usual, onErr is supposed either produce a result or raise
* an exception.
*/
export declare function handle<T>(name: any, code: (p1: Frame<T>) => void, onErr: (p1: Frame<T>, p2: Error) => void): Result<T>;
export declare function start<T>(func: () => Result<T>, opt_name?: string): Task;
/**
* Frame state.
* @enum {number}
*/
export declare enum FrameState {
INIT = 0,
ACTIVE = 1,
FINISHED = 2,
DEAD = 3
}
export declare class TimerImpl implements Timer {
/**
* @override
*/
currentTime(): number;
/**
* @override
*/
setTimeout(fn: () => void, delay: number): number;
/**
* @override
*/
clearTimeout(token: number): void;
}
/**
* A class to create tasks.
*/
export declare class Scheduler {
timer: Timer;
timeout: number;
slice: number;
sliceOverTime: number;
queue: Base.PriorityQueue;
wakeupTime: number | null;
timeoutToken: number | null;
inTimeSlice: boolean;
order: number;
constructor(timer: Timer);
/**
* Sets time slice length.
* @param slice length in milliseconds.
*/
setSlice(slice: number): void;
/**
* Sets timeout between time slices.
* @param timeout in milliseconds.
*/
setTimeout(timeout: number): void;
/**
* Checks if the current time slice is over.
*/
isTimeSliceOver(): boolean;
private arm;
schedule(continuation: Continuation<any>, opt_delay?: number): void;
private doTimeSlice;
run(func: () => Result<any>, opt_name?: string): Task;
}
/**
* Task suspension point.
* @template T
*/
export declare class Continuation<T> implements Base.Comparable {
task: Task;
scheduledTime: number;
order: number;
result: T;
canceled: boolean;
constructor(task: Task);
/**
* @override
*/
compare(otherComp: Base.Comparable): number;
/**
* Continuation's task
*/
getTask(): Task;
/**
* Schedule task continuation after the given (optional) delay.
* @param opt_delay optional delay in milliseconds.
*/
schedule(result: T, opt_delay?: number): void;
resumeInternal(): boolean;
/**
* Cancel continuation
*/
cancel(): void;
}
/**
* An asynchronous, time-sliced task.
*/
export declare class Task {
scheduler: Scheduler;
name: string;
callbacks: (() => void)[];
exception: Error | null;
running: boolean;
result: any;
waitTarget: string | null;
top: Frame<any> | null;
continuation: Continuation<any> | null;
constructor(scheduler: Scheduler, name: string);
/**
* @return task name.
*/
getName(): string;
/**
* @param err exception to throw in the task's context.
*/
interrupt(err: Error): void;
/**
* @return this task's scheduler.
*/
getScheduler(): Scheduler;
/**
* @return true if task is still running.
*/
isRunning(): boolean;
/**
* Register a callback to be called when the task is done. Callback is not
* executed in any task context. Multiple callbacks can be registered and
* they will be called in the registration order.
*/
whenDone(callback: () => void): void;
/**
* Wait for task to finish (from another task).
*/
join(): Result<any>;
/**
* Unwind the stack. We have two stacks: async (maintained by frame
* parent link) and sync (regular JavaScript stack).
*/
unwind(): void;
raise(err: Error, opt_frame?: Frame<any>): void;
/**
* Fill the stack trace in the exception
* @param err exception
*/
fillStack(err: Error): void;
}
/**
* @template T
*/
export declare class SyncResultImpl<T> implements Result<T> {
value: T;
constructor(value: T);
/**
* @override
*/
then(callback: (T: any) => void): void;
/**
* @override
*/
thenAsync<T1>(callback: (p1: T) => Result<T1>): Result<T1>;
/**
* @override
*/
thenReturn<T1>(result: T1): SyncResultImpl<T1>;
/**
* @override
*/
thenFinish(frame: Frame<T>): void;
/**
* @override
*/
isPending(): boolean;
/**
* @override
*/
get(): T | null;
}
/**
* @template T
*/
export declare class ResultImpl<T> implements Result<T> {
readonly frame: Frame<T>;
constructor(frame: Frame<T>);
/**
* @override
*/
then(callback: (p1: T) => void): void;
/**
* @override
*/
thenAsync<T1>(callback: (p1: T) => Result<T1>): Result<T1>;
/**
* @override
*/
thenReturn<T1>(result: T1): Result<any> | SyncResultImpl<T1>;
/**
* @override
*/
thenFinish(frame: Frame<T>): void;
/**
* @override
*/
isPending(): boolean;
/**
* @override
*/
get(): T | null;
}
/**
* Asynchronous execution frame. Corresponds to an asynchronous function
* invocation.
* @template T
*/
export declare class Frame<T> {
task: Task;
parent: Frame<T>;
name: string;
res: T;
state: FrameState;
callback: ((p1: any) => void) | null;
handler: ((p1: Frame<any>, p2: Error) => void) | null;
constructor(task: Task, parent: Frame<T>, name: string);
private checkEnvironment;
/**
* @return to be returned as this asynchronous function return value.
*/
result(): Result<T>;
finish(res: T): void;
getTask(): Task;
/**
* @return frame name.
*/
getName(): string;
getScheduler(): Scheduler;
then(callback: (p1: T) => void): void;
/**
* If this task was executed longer than task's slice parameter.
* @return holds true
*/
timeSlice(): Result<boolean>;
/**
* Yield to other tasks for the specified time.
* @param delay in milliseconds.
* @return holds true
*/
sleep(delay: number): Result<boolean>;
/**
* Repeatedly execute the given function asynchronously until it returns
* false.
* @return holds true.
*/
loop(func: () => Result<boolean>): Result<boolean>;
/**
* Similar to loop(), but provides a Frame for loop body function.
* @return holds true.
*/
loopWithFrame(func: (p1: LoopBodyFrame) => void): Result<boolean>;
suspend(opt_waitTarget?: any): Continuation<T>;
}
export declare class LoopBodyFrame extends Frame<boolean> {
constructor(task: Task, parent: Frame<boolean>);
continueLoop(): void;
breakLoop(): void;
}
export declare class EventItem {
event: Base.Event;
next: EventItem;
constructor(event: Base.Event);
}
/**
* An class to listen to evens and present them as a readable asynchronous
* stream to tasks.
*/
export declare class EventSource {
continuation: Continuation<boolean>;
listeners: {
target: Base.EventTarget;
type: string;
listener: Base.EventListener;
}[];
head: EventItem;
tail: EventItem;
constructor();
/**
* Attaches as an event listener to an EventTarget.
*/
attach(target: Base.EventTarget, type: string, opt_preventDefault?: boolean): void;
detach(target: Base.EventTarget, type: string): void;
/**
* Read next dispatched event, blocking the current task if needed.
*/
nextEvent(): Result<Base.Event>;
}