Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)

* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973

* disable strict null check
This commit is contained in:
Anthony Dresser
2019-07-15 22:35:46 -07:00
committed by GitHub
parent f720ec642f
commit 0b7e7ddbf9
2406 changed files with 59140 additions and 35464 deletions

View File

@@ -3,17 +3,27 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IDisposable, combinedDisposable, Disposable } from 'vs/base/common/lifecycle';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
export interface ITelemetryData {
from?: string;
target?: string;
readonly from?: string;
readonly target?: string;
[key: string]: any;
}
export interface IAction extends IDisposable {
export type WorkbenchActionExecutedClassification = {
id: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
from: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
};
export type WorkbenchActionExecutedEvent = {
id: string;
from: string;
};
export interface IAction extends IDisposable {
readonly id: string;
label: string;
tooltip: string;
class: string | undefined;
@@ -25,44 +35,44 @@ export interface IAction extends IDisposable {
export interface IActionRunner extends IDisposable {
run(action: IAction, context?: any): Promise<any>;
onDidRun: Event<IRunEvent>;
onDidBeforeRun: Event<IRunEvent>;
readonly onDidRun: Event<IRunEvent>;
readonly onDidBeforeRun: Event<IRunEvent>;
}
export interface IActionViewItem {
actionRunner: IActionRunner;
export interface IActionViewItem extends IDisposable {
readonly actionRunner: IActionRunner;
setActionContext(context: any): void;
render(element: any /* HTMLElement */): void;
isEnabled(): boolean;
focus(): void;
blur(): void;
dispose(): void;
}
export interface IActionChangeEvent {
label?: string;
tooltip?: string;
class?: string;
enabled?: boolean;
checked?: boolean;
radio?: boolean;
readonly label?: string;
readonly tooltip?: string;
readonly class?: string;
readonly enabled?: boolean;
readonly checked?: boolean;
readonly radio?: boolean;
}
export class Action implements IAction {
export class Action extends Disposable implements IAction {
protected _onDidChange = new Emitter<IActionChangeEvent>();
protected _onDidChange = this._register(new Emitter<IActionChangeEvent>());
readonly onDidChange: Event<IActionChangeEvent> = this._onDidChange.event;
protected _id: string;
protected readonly _id: string;
protected _label: string;
protected _tooltip: string;
protected _cssClass: string | undefined;
protected _enabled: boolean;
protected _checked: boolean;
protected _radio: boolean;
protected _actionCallback?: (event?: any) => Promise<any>;
protected readonly _actionCallback?: (event?: any) => Promise<any>;
constructor(id: string, label: string = '', cssClass: string = '', enabled: boolean = true, actionCallback?: (event?: any) => Promise<any>) {
super();
this._id = id;
this._label = label;
this._cssClass = cssClass;
@@ -82,7 +92,7 @@ export class Action implements IAction {
this._setLabel(value);
}
protected _setLabel(value: string): void {
private _setLabel(value: string): void {
if (this._label !== value) {
this._label = value;
this._onDidChange.fire({ label: value });
@@ -171,16 +181,12 @@ export class Action implements IAction {
return Promise.resolve(true);
}
dispose() {
this._onDidChange.dispose();
}
}
export interface IRunEvent {
action: IAction;
result?: any;
error?: any;
readonly action: IAction;
readonly result?: any;
readonly error?: any;
}
export class ActionRunner extends Disposable implements IActionRunner {
@@ -217,8 +223,8 @@ export class RadioGroup extends Disposable {
constructor(readonly actions: Action[]) {
super();
this._register(combinedDisposable(actions.map(action => {
return action.onDidChange(e => {
for (const action of actions) {
this._register(action.onDidChange(e => {
if (e.checked && action.checked) {
for (const candidate of actions) {
if (candidate !== action) {
@@ -226,7 +232,7 @@ export class RadioGroup extends Disposable {
}
}
}
});
})));
}));
}
}
}

View File

@@ -295,9 +295,9 @@ function topStep<T>(array: ReadonlyArray<T>, compare: (a: T, b: T) => number, re
/**
* @returns a new array with all falsy values removed. The original array IS NOT modified.
*/
export function coalesce<T>(array: Array<T | undefined | null>): T[] {
export function coalesce<T>(array: ReadonlyArray<T | undefined | null>): T[] {
if (!array) {
return array;
return undefined; // {{SQL CARBON EDIT}} @anthonydresser strict-null-checks
}
return <T[]>array.filter(e => !!e);
}
@@ -336,7 +336,9 @@ export function isFalsyOrEmpty(obj: any): boolean {
/**
* @returns True if the provided object is an array and has at least one element.
*/
export function isNonEmptyArray<T>(obj: ReadonlyArray<T> | undefined | null): obj is Array<T> {
export function isNonEmptyArray<T>(obj: T[] | undefined | null): obj is T[];
export function isNonEmptyArray<T>(obj: readonly T[] | undefined | null): obj is readonly T[];
export function isNonEmptyArray<T>(obj: T[] | readonly T[] | undefined | null): obj is T[] | readonly T[] {
return Array.isArray(obj) && obj.length > 0;
}

View File

@@ -6,7 +6,7 @@
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import * as errors from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
export function isThenable<T>(obj: any): obj is Promise<T> {
@@ -415,11 +415,11 @@ export class Limiter<T> {
this._onFinished = new Emitter<void>();
}
public get onFinished(): Event<void> {
get onFinished(): Event<void> {
return this._onFinished.event;
}
public get size(): number {
get size(): number {
return this._size;
// return this.runningPromises + this.outstandingPromises.length;
}
@@ -455,7 +455,7 @@ export class Limiter<T> {
}
}
public dispose(): void {
dispose(): void {
this._onFinished.dispose();
}
}
@@ -475,35 +475,30 @@ export class Queue<T> extends Limiter<T> {
* by disposing them once the queue is empty.
*/
export class ResourceQueue {
private queues: { [path: string]: Queue<void> };
private queues: Map<string, Queue<void>> = new Map();
constructor() {
this.queues = Object.create(null);
}
public queueFor(resource: URI): Queue<void> {
queueFor(resource: URI): Queue<void> {
const key = resource.toString();
if (!this.queues[key]) {
if (!this.queues.has(key)) {
const queue = new Queue<void>();
queue.onFinished(() => {
queue.dispose();
delete this.queues[key];
this.queues.delete(key);
});
this.queues[key] = queue;
this.queues.set(key, queue);
}
return this.queues[key];
return this.queues.get(key)!;
}
}
export class TimeoutTimer extends Disposable {
export class TimeoutTimer implements IDisposable {
private _token: any;
constructor();
constructor(runner: () => void, timeout: number);
constructor(runner?: () => void, timeout?: number) {
super();
this._token = -1;
if (typeof runner === 'function' && typeof timeout === 'number') {
@@ -513,7 +508,6 @@ export class TimeoutTimer extends Disposable {
dispose(): void {
this.cancel();
super.dispose();
}
cancel(): void {
@@ -543,18 +537,16 @@ export class TimeoutTimer extends Disposable {
}
}
export class IntervalTimer extends Disposable {
export class IntervalTimer implements IDisposable {
private _token: any;
constructor() {
super();
this._token = -1;
}
dispose(): void {
this.cancel();
super.dispose();
}
cancel(): void {

View File

@@ -78,7 +78,10 @@ export class VSBuffer {
}
slice(start?: number, end?: number): VSBuffer {
return new VSBuffer(this.buffer.slice(start, end));
// IMPORTANT: use subarray instead of slice because TypedArray#slice
// creates shallow copy and NodeBuffer#slice doesn't. The use of subarray
// ensures the same, performant, behaviour.
return new VSBuffer(this.buffer.subarray(start!/*bad lib.d.ts*/, end));
}
set(array: VSBuffer, offset?: number): void {
@@ -138,18 +141,13 @@ export interface VSBufferReadable {
read(): VSBuffer | null;
}
/**
* A buffer readable stream emits data to listeners. The stream
* will only start emitting when the first data listener has
* been added or the resume() method has been called.
*/
export interface VSBufferReadableStream {
export interface ReadableStream<T> {
/**
* The 'data' event is emitted whenever the stream is
* relinquishing ownership of a chunk of data to a consumer.
*/
on(event: 'data', callback: (chunk: VSBuffer) => void): void;
on(event: 'data', callback: (chunk: T) => void): void;
/**
* Emitted when any error occurs.
@@ -166,19 +164,34 @@ export interface VSBufferReadableStream {
/**
* Stops emitting any events until resume() is called.
*/
pause(): void;
pause?(): void;
/**
* Starts emitting events again after pause() was called.
*/
resume(): void;
resume?(): void;
/**
* Destroys the stream and stops emitting any event.
*/
destroy?(): void;
}
/**
* A readable stream that sends data via VSBuffer.
*/
export interface VSBufferReadableStream extends ReadableStream<VSBuffer> {
pause(): void;
resume(): void;
destroy(): void;
}
export function isVSBufferReadableStream(obj: any): obj is VSBufferReadableStream {
const candidate: VSBufferReadableStream = obj;
return candidate && [candidate.on, candidate.pause, candidate.resume, candidate.destroy].every(fn => typeof fn === 'function');
}
/**
* Helper to fully read a VSBuffer readable into a single buffer.
*/
@@ -236,6 +249,19 @@ export function bufferToStream(buffer: VSBuffer): VSBufferReadableStream {
return stream;
}
/**
* Helper to create a VSBufferStream from a Uint8Array stream.
*/
export function toVSBufferReadableStream(stream: ReadableStream<Uint8Array | string>): VSBufferReadableStream {
const vsbufferStream = writeableBufferStream();
stream.on('data', data => vsbufferStream.write(typeof data === 'string' ? VSBuffer.fromString(data) : VSBuffer.wrap(data)));
stream.on('end', () => vsbufferStream.end());
stream.on('error', error => vsbufferStream.error(error));
return vsbufferStream;
}
/**
* Helper to create a VSBufferStream that can be pushed
* buffers to. Will only start to emit data when a listener

View File

@@ -4,10 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { IDisposable } from 'vs/base/common/lifecycle';
export interface CacheResult<T> {
export interface CacheResult<T> extends IDisposable {
promise: Promise<T>;
dispose(): void;
}
export class Cache<T> {

View File

@@ -46,9 +46,9 @@ export function size<T>(from: IStringDictionary<T> | INumberDictionary<T>): numb
}
export function first<T>(from: IStringDictionary<T> | INumberDictionary<T>): T | undefined {
for (let key in from) {
for (const key in from) {
if (hasOwnProperty.call(from, key)) {
return from[key];
return (from as any)[key];
}
}
return undefined;
@@ -99,3 +99,43 @@ export function fromMap<T>(original: Map<string, T>): IStringDictionary<T> {
}
return result;
}
export class SetMap<K, V> {
private map = new Map<K, Set<V>>();
add(key: K, value: V): void {
let values = this.map.get(key);
if (!values) {
values = new Set<V>();
this.map.set(key, values);
}
values.add(value);
}
delete(key: K, value: V): void {
const values = this.map.get(key);
if (!values) {
return;
}
values.delete(value);
if (values.size === 0) {
this.map.delete(key);
}
}
forEach(key: K, fn: (value: V) => void): void {
const values = this.map.get(key);
if (!values) {
return;
}
values.forEach(fn);
}
}

View File

@@ -7,28 +7,26 @@ import * as strings from 'vs/base/common/strings';
import { sep } from 'vs/base/common/path';
import { IdleValue } from 'vs/base/common/async';
let intlFileNameCollator: IdleValue<{ collator: Intl.Collator, collatorIsNumeric: boolean }>;
export function setFileNameComparer(collator: IdleValue<{ collator: Intl.Collator, collatorIsNumeric: boolean }>): void {
intlFileNameCollator = collator;
}
const intlFileNameCollator: IdleValue<{ collator: Intl.Collator, collatorIsNumeric: boolean }> = new IdleValue(() => {
const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
return {
collator: collator,
collatorIsNumeric: collator.resolvedOptions().numeric
};
});
export function compareFileNames(one: string | null, other: string | null, caseSensitive = false): number {
if (intlFileNameCollator) {
const a = one || '';
const b = other || '';
const result = intlFileNameCollator.getValue().collator.compare(a, b);
const a = one || '';
const b = other || '';
const result = intlFileNameCollator.getValue().collator.compare(a, b);
// Using the numeric option in the collator will
// make compare(`foo1`, `foo01`) === 0. We must disambiguate.
if (intlFileNameCollator.getValue().collatorIsNumeric && result === 0 && a !== b) {
return a < b ? -1 : 1;
}
return result;
// Using the numeric option in the collator will
// make compare(`foo1`, `foo01`) === 0. We must disambiguate.
if (intlFileNameCollator.getValue().collatorIsNumeric && result === 0 && a !== b) {
return a < b ? -1 : 1;
}
return noIntlCompareFileNames(one, other, caseSensitive);
return result;
}
const FileNameMatch = /^(.*?)(\.([^.]*))?$/;
@@ -54,46 +52,27 @@ export function noIntlCompareFileNames(one: string | null, other: string | null,
}
export function compareFileExtensions(one: string | null, other: string | null): number {
if (intlFileNameCollator) {
const [oneName, oneExtension] = extractNameAndExtension(one);
const [otherName, otherExtension] = extractNameAndExtension(other);
const [oneName, oneExtension] = extractNameAndExtension(one);
const [otherName, otherExtension] = extractNameAndExtension(other);
let result = intlFileNameCollator.getValue().collator.compare(oneExtension, otherExtension);
let result = intlFileNameCollator.getValue().collator.compare(oneExtension, otherExtension);
if (result === 0) {
// Using the numeric option in the collator will
// make compare(`foo1`, `foo01`) === 0. We must disambiguate.
if (intlFileNameCollator.getValue().collatorIsNumeric && oneExtension !== otherExtension) {
return oneExtension < otherExtension ? -1 : 1;
}
// Extensions are equal, compare filenames
result = intlFileNameCollator.getValue().collator.compare(oneName, otherName);
if (intlFileNameCollator.getValue().collatorIsNumeric && result === 0 && oneName !== otherName) {
return oneName < otherName ? -1 : 1;
}
if (result === 0) {
// Using the numeric option in the collator will
// make compare(`foo1`, `foo01`) === 0. We must disambiguate.
if (intlFileNameCollator.getValue().collatorIsNumeric && oneExtension !== otherExtension) {
return oneExtension < otherExtension ? -1 : 1;
}
return result;
// Extensions are equal, compare filenames
result = intlFileNameCollator.getValue().collator.compare(oneName, otherName);
if (intlFileNameCollator.getValue().collatorIsNumeric && result === 0 && oneName !== otherName) {
return oneName < otherName ? -1 : 1;
}
}
return noIntlCompareFileExtensions(one, other);
}
function noIntlCompareFileExtensions(one: string | null, other: string | null): number {
const [oneName, oneExtension] = extractNameAndExtension(one && one.toLowerCase());
const [otherName, otherExtension] = extractNameAndExtension(other && other.toLowerCase());
if (oneExtension !== otherExtension) {
return oneExtension < otherExtension ? -1 : 1;
}
if (oneName === otherName) {
return 0;
}
return oneName < otherName ? -1 : 1;
return result;
}
function extractNameAndExtension(str?: string | null): [string, string] {

View File

@@ -131,7 +131,10 @@ export function log(entry: IRemoteConsoleLog, label: string): void {
}
// Log it
console[entry.severity].apply(console, consoleArgs);
if (typeof (console as any)[entry.severity] !== 'function') {
throw new Error('Unknown console method');
}
(console as any)[entry.severity].apply(console, consoleArgs);
}
function color(color: string): string {

View File

@@ -10,7 +10,7 @@ import * as arrays from 'vs/base/common/arrays';
function exceptionToErrorMessage(exception: any, verbose: boolean): string {
if (exception.message) {
if (verbose && (exception.stack || exception.stacktrace)) {
return nls.localize('stackTrace.format', "{0}: {1}", detectSystemErrorMessage(exception), exception.stack || exception.stacktrace);
return nls.localize('stackTrace.format', "{0}: {1}", detectSystemErrorMessage(exception), stackToString(exception.stack) || stackToString(exception.stacktrace));
}
return detectSystemErrorMessage(exception);
@@ -19,6 +19,14 @@ function exceptionToErrorMessage(exception: any, verbose: boolean): string {
return nls.localize('error.defaultMessage', "An unknown error occurred. Please consult the log for more details.");
}
function stackToString(stack: string[] | string | undefined): string | undefined {
if (Array.isArray(stack)) {
return stack.join('\n');
}
return stack;
}
function detectSystemErrorMessage(exception: any): string {
// See https://nodejs.org/api/errors.html#errors_class_system_error

View File

@@ -6,11 +6,11 @@
import { IAction } from 'vs/base/common/actions';
export interface IErrorOptions {
actions?: IAction[];
actions?: ReadonlyArray<IAction>;
}
export interface IErrorWithActions {
actions?: IAction[];
actions?: ReadonlyArray<IAction>;
}
export function isErrorWithActions(obj: any): obj is IErrorWithActions {

View File

@@ -5,7 +5,7 @@
import { onUnexpectedError } from 'vs/base/common/errors';
import { once as onceFn } from 'vs/base/common/functional';
import { combinedDisposable, Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, toDisposable, combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { LinkedList } from 'vs/base/common/linkedList';
/**
@@ -13,12 +13,11 @@ import { LinkedList } from 'vs/base/common/linkedList';
* can be subscribed. The event is the subscriber function itself.
*/
export interface Event<T> {
(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;
(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;
}
export namespace Event {
const _disposable = { dispose() { } };
export const None: Event<any> = function () { return _disposable; };
export const None: Event<any> = () => Disposable.None;
/**
* Given an event, returns another event which only fires once.
@@ -50,7 +49,7 @@ export namespace Event {
/**
* Given an event and a `map` function, returns another event which maps each element
* throught the mapping function.
* through the mapping function.
*/
export function map<I, O>(event: Event<I>, map: (i: I) => O): Event<O> {
return snapshot((listener, thisArgs = null, disposables?) => event(i => listener.call(thisArgs, map(i)), null, disposables));
@@ -86,12 +85,12 @@ export namespace Event {
* whenever any of the provided events emit.
*/
export function any<T>(...events: Event<T>[]): Event<T> {
return (listener, thisArgs = null, disposables?) => combinedDisposable(events.map(event => event(e => listener.call(thisArgs, e), null, disposables)));
return (listener, thisArgs = null, disposables?) => combinedDisposable(...events.map(event => event(e => listener.call(thisArgs, e), null, disposables)));
}
/**
* Given an event and a `merge` function, returns another event which maps each element
* and the cummulative result throught the `merge` function. Similar to `map`, but with memory.
* and the cumulative result through the `merge` function. Similar to `map`, but with memory.
*/
export function reduce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, initial?: O): Event<O> {
let output: O | undefined = initial;
@@ -272,7 +271,7 @@ export namespace Event {
filter(fn: (e: T) => boolean): IChainableEvent<T>;
reduce<R>(merge: (last: R | undefined, event: T) => R, initial?: R): IChainableEvent<R>;
latch(): IChainableEvent<T>;
on(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;
on(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;
once(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;
}
@@ -300,7 +299,7 @@ export namespace Event {
return new ChainableEvent(latch(this.event));
}
on(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[]) {
on(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[] | DisposableStore) {
return this.event(listener, thisArgs, disposables);
}
@@ -477,7 +476,7 @@ export class Emitter<T> {
*/
get event(): Event<T> {
if (!this._event) {
this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]) => {
this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {
if (!this._listeners) {
this._listeners = new LinkedList();
}
@@ -522,7 +521,9 @@ export class Emitter<T> {
}
}
};
if (Array.isArray(disposables)) {
if (disposables instanceof DisposableStore) {
disposables.add(result);
} else if (Array.isArray(disposables)) {
disposables.push(result);
}

View File

@@ -125,7 +125,11 @@ const wordSeparators = new Set<number>();
.forEach(s => wordSeparators.add(s.charCodeAt(0)));
function isWordSeparator(code: number): boolean {
return wordSeparators.has(code);
return isWhitespace(code) || wordSeparators.has(code);
}
function charactersMatch(codeA: number, codeB: number): boolean {
return (codeA === codeB) || (isWordSeparator(codeA) && isWordSeparator(codeB));
}
function isAlphanumeric(code: number): boolean {
@@ -298,7 +302,7 @@ function _matchesWords(word: string, target: string, i: number, j: number, conti
return [];
} else if (j === target.length) {
return null;
} else if (word[i] !== target[j]) {
} else if (!charactersMatch(word.charCodeAt(i), target.charCodeAt(j))) {
return null;
} else {
let result: IMatch[] | null = null;
@@ -316,9 +320,8 @@ function _matchesWords(word: string, target: string, i: number, j: number, conti
function nextWord(word: string, start: number): number {
for (let i = start; i < word.length; i++) {
const c = word.charCodeAt(i);
if (isWhitespace(c) || (i > 0 && isWhitespace(word.charCodeAt(i - 1))) ||
isWordSeparator(c) || (i > 0 && isWordSeparator(word.charCodeAt(i - 1)))) {
if (isWordSeparator(word.charCodeAt(i)) ||
(i > 0 && isWordSeparator(word.charCodeAt(i - 1)))) {
return i;
}
}
@@ -492,7 +495,7 @@ function isUpperCaseAtPos(pos: number, word: string, wordLow: string): boolean {
return word[pos] !== wordLow[pos];
}
function isPatternInWord(patternLow: string, patternPos: number, patternLen: number, wordLow: string, wordPos: number, wordLen: number): boolean {
export function isPatternInWord(patternLow: string, patternPos: number, patternLen: number, wordLow: string, wordPos: number, wordLen: number): boolean {
while (patternPos < patternLen && wordPos < wordLen) {
if (patternLow[patternPos] === wordLow[wordPos]) {
patternPos += 1;

View File

@@ -458,14 +458,14 @@ export function parse(arg1: string | IExpression | IRelativePattern, options: IG
if (parsedPattern === NULL) {
return FALSE;
}
const resultPattern = function (path: string, basename: string) {
const resultPattern: ParsedPattern & { allBasenames?: string[]; allPaths?: string[]; } = function (path: string, basename: string) {
return !!parsedPattern(path, basename);
};
if (parsedPattern.allBasenames) {
(<ParsedStringPattern><any>resultPattern).allBasenames = parsedPattern.allBasenames;
resultPattern.allBasenames = parsedPattern.allBasenames;
}
if (parsedPattern.allPaths) {
(<ParsedStringPattern><any>resultPattern).allPaths = parsedPattern.allPaths;
resultPattern.allPaths = parsedPattern.allPaths;
}
return resultPattern;
}

View File

@@ -92,3 +92,25 @@ export function removeMarkdownEscapes(text: string): string {
}
return text.replace(/\\([\\`*_{}[\]()#+\-.!])/g, '$1');
}
export function parseHrefAndDimensions(href: string): { href: string, dimensions: string[] } {
const dimensions: string[] = [];
const splitted = href.split('|').map(s => s.trim());
href = splitted[0];
const parameters = splitted[1];
if (parameters) {
const heightFromParams = /height=(\d+)/.exec(parameters);
const widthFromParams = /width=(\d+)/.exec(parameters);
const height = heightFromParams ? heightFromParams[1] : '';
const width = widthFromParams ? widthFromParams[1] : '';
const widthIsFinite = isFinite(parseInt(width));
const heightIsFinite = isFinite(parseInt(height));
if (widthIsFinite) {
dimensions.push(`width="${width}"`);
}
if (heightIsFinite) {
dimensions.push(`height="${height}"`);
}
}
return { href, dimensions };
}

View File

@@ -5,6 +5,45 @@
import { once } from 'vs/base/common/functional';
/**
* Enables logging of potentially leaked disposables.
*
* A disposable is considered leaked if it is not disposed or not registered as the child of
* another disposable. This tracking is very simple an only works for classes that either
* extend Disposable or use a DisposableStore. This means there are a lot of false positives.
*/
const TRACK_DISPOSABLES = false;
const __is_disposable_tracked__ = '__is_disposable_tracked__';
function markTracked<T extends IDisposable>(x: T): void {
if (!TRACK_DISPOSABLES) {
return;
}
if (x && x !== Disposable.None) {
try {
(x as any)[__is_disposable_tracked__] = true;
} catch {
// noop
}
}
}
function trackDisposable<T extends IDisposable>(x: T): T {
if (!TRACK_DISPOSABLES) {
return x;
}
const stack = new Error('Potentially leaked disposable').stack!;
setTimeout(() => {
if (!(x as any)[__is_disposable_tracked__]) {
console.log(stack);
}
}, 3000);
return x;
}
export interface IDisposable {
dispose(): void;
}
@@ -15,56 +54,156 @@ export function isDisposable<E extends object>(thing: E): thing is E & IDisposab
}
export function dispose<T extends IDisposable>(disposable: T): T;
export function dispose<T extends IDisposable>(...disposables: Array<T | undefined>): T[];
export function dispose<T extends IDisposable>(disposables: T[]): T[];
export function dispose<T extends IDisposable>(first: T | T[], ...rest: T[]): T | T[] | undefined {
if (Array.isArray(first)) {
first.forEach(d => d && d.dispose());
export function dispose<T extends IDisposable>(disposable: T | undefined): T | undefined;
export function dispose<T extends IDisposable>(disposables: Array<T>): Array<T>;
export function dispose<T extends IDisposable>(disposables: ReadonlyArray<T>): ReadonlyArray<T>;
export function dispose<T extends IDisposable>(disposables: T | T[] | undefined): T | T[] | undefined {
if (Array.isArray(disposables)) {
disposables.forEach(d => {
if (d) {
markTracked(d);
d.dispose();
}
});
return [];
} else if (rest.length === 0) {
if (first) {
first.dispose();
return first;
}
return undefined;
} else if (disposables) {
markTracked(disposables);
disposables.dispose();
return disposables;
} else {
dispose(first);
dispose(rest);
return [];
return undefined;
}
}
export function combinedDisposable(disposables: IDisposable[]): IDisposable {
return { dispose: () => dispose(disposables) };
export function combinedDisposable(...disposables: IDisposable[]): IDisposable {
disposables.forEach(markTracked);
return trackDisposable({ dispose: () => dispose(disposables) });
}
export function toDisposable(fn: () => void): IDisposable {
return { dispose() { fn(); } };
const self = trackDisposable({
dispose: () => {
markTracked(self);
fn();
}
});
return self;
}
export class DisposableStore implements IDisposable {
private _toDispose = new Set<IDisposable>();
private _isDisposed = false;
/**
* Dispose of all registered disposables and mark this object as disposed.
*
* Any future disposables added to this object will be disposed of on `add`.
*/
public dispose(): void {
if (this._isDisposed) {
return;
}
markTracked(this);
this._isDisposed = true;
this.clear();
}
/**
* Dispose of all registered disposables but do not mark this object as disposed.
*/
public clear(): void {
this._toDispose.forEach(item => item.dispose());
this._toDispose.clear();
}
public add<T extends IDisposable>(t: T): T {
if (!t) {
return t;
}
if ((t as any as DisposableStore) === this) {
throw new Error('Cannot register a disposable on itself!');
}
markTracked(t);
if (this._isDisposed) {
console.warn(new Error('Registering disposable on object that has already been disposed of').stack);
t.dispose();
} else {
this._toDispose.add(t);
}
return t;
}
}
export abstract class Disposable implements IDisposable {
static None = Object.freeze<IDisposable>({ dispose() { } });
protected _toDispose: IDisposable[] = [];
protected get toDispose(): IDisposable[] { return this._toDispose; }
private readonly _store = new DisposableStore();
private _lifecycle_disposable_isDisposed = false;
constructor() {
trackDisposable(this);
}
public dispose(): void {
this._lifecycle_disposable_isDisposed = true;
this._toDispose = dispose(this._toDispose);
markTracked(this);
this._store.dispose();
}
protected _register<T extends IDisposable>(t: T): T {
if (this._lifecycle_disposable_isDisposed) {
console.warn('Registering disposable on object that has already been disposed.');
t.dispose();
} else {
this._toDispose.push(t);
if ((t as any as Disposable) === this) {
throw new Error('Cannot register a disposable on itself!');
}
return this._store.add(t);
}
}
/**
* Manages the lifecycle of a disposable value that may be changed.
*
* This ensures that when the the disposable value is changed, the previously held disposable is disposed of. You can
* also register a `MutableDisposable` on a `Disposable` to ensure it is automatically cleaned up.
*/
export class MutableDisposable<T extends IDisposable> implements IDisposable {
private _value?: T;
private _isDisposed = false;
constructor() {
trackDisposable(this);
}
get value(): T | undefined {
return this._isDisposed ? undefined : this._value;
}
set value(value: T | undefined) {
if (this._isDisposed || value === this._value) {
return;
}
return t;
if (this._value) {
this._value.dispose();
}
if (value) {
markTracked(value);
}
this._value = value;
}
clear() {
this.value = undefined;
}
dispose(): void {
this._isDisposed = true;
markTracked(this);
if (this._value) {
this._value.dispose();
}
this._value = undefined;
}
}
@@ -74,22 +213,23 @@ export interface IReference<T> extends IDisposable {
export abstract class ReferenceCollection<T> {
private references: { [key: string]: { readonly object: T; counter: number; } } = Object.create(null);
private references: Map<string, { readonly object: T; counter: number; }> = new Map();
constructor() { }
acquire(key: string): IReference<T> {
let reference = this.references[key];
let reference = this.references.get(key);
if (!reference) {
reference = this.references[key] = { counter: 0, object: this.createReferencedObject(key) };
reference = { counter: 0, object: this.createReferencedObject(key) };
this.references.set(key, reference);
}
const { object } = reference;
const dispose = once(() => {
if (--reference.counter === 0) {
this.destroyReferencedObject(key, reference.object);
delete this.references[key];
if (--reference!.counter === 0) {
this.destroyReferencedObject(key, reference!.object);
this.references.delete(key);
}
});

View File

@@ -7,6 +7,9 @@ import { basename, posix, extname } from 'vs/base/common/path';
import { endsWith, startsWithUTF8BOM, startsWith } from 'vs/base/common/strings';
import { coalesce } from 'vs/base/common/arrays';
import { match } from 'vs/base/common/glob';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { DataUri } from 'vs/base/common/resources';
export const MIME_TEXT = 'text/plain';
export const MIME_BINARY = 'application/octet-stream';
@@ -106,12 +109,28 @@ export function clearTextMimes(onlyUserConfigured?: boolean): void {
/**
* Given a file, return the best matching mime type for it
*/
export function guessMimeTypes(path: string | null, firstLine?: string): string[] {
export function guessMimeTypes(resource: URI | null, firstLine?: string): string[] {
let path: string | undefined;
if (resource) {
switch (resource.scheme) {
case Schemas.file:
path = resource.fsPath;
break;
case Schemas.data:
const metadata = DataUri.parseMetaData(resource);
path = metadata.get(DataUri.META_DATA_LABEL);
break;
default:
path = resource.path;
}
}
if (!path) {
return [MIME_UNKNOWN];
}
path = path.toLowerCase();
const filename = basename(path);
// 1.) User configured mappings have highest priority
@@ -255,52 +274,54 @@ interface MapExtToMediaMimes {
// Known media mimes that we can handle
const mapExtToMediaMimes: MapExtToMediaMimes = {
'.aac': 'audio/x-aac',
'.avi': 'video/x-msvideo',
'.bmp': 'image/bmp',
'.flv': 'video/x-flv',
'.gif': 'image/gif',
'.jpg': 'image/jpg',
'.jpeg': 'image/jpg',
'.jpe': 'image/jpg',
'.png': 'image/png',
'.tiff': 'image/tiff',
'.tif': 'image/tiff',
'.ico': 'image/x-icon',
'.tga': 'image/x-tga',
'.psd': 'image/vnd.adobe.photoshop',
'.webp': 'image/webp',
'.jpe': 'image/jpg',
'.jpeg': 'image/jpg',
'.jpg': 'image/jpg',
'.m1v': 'video/mpeg',
'.m2a': 'audio/mpeg',
'.m2v': 'video/mpeg',
'.m3a': 'audio/mpeg',
'.mid': 'audio/midi',
'.midi': 'audio/midi',
'.mp4a': 'audio/mp4',
'.mpga': 'audio/mpeg',
'.mk3d': 'video/x-matroska',
'.mks': 'video/x-matroska',
'.mkv': 'video/x-matroska',
'.mov': 'video/quicktime',
'.movie': 'video/x-sgi-movie',
'.mp2': 'audio/mpeg',
'.mp2a': 'audio/mpeg',
'.mp3': 'audio/mpeg',
'.m2a': 'audio/mpeg',
'.m3a': 'audio/mpeg',
'.oga': 'audio/ogg',
'.ogg': 'audio/ogg',
'.spx': 'audio/ogg',
'.aac': 'audio/x-aac',
'.wav': 'audio/x-wav',
'.wma': 'audio/x-ms-wma',
'.mp4': 'video/mp4',
'.mp4a': 'audio/mp4',
'.mp4v': 'video/mp4',
'.mpg4': 'video/mp4',
'.mpe': 'video/mpeg',
'.mpeg': 'video/mpeg',
'.mpg': 'video/mpeg',
'.mpe': 'video/mpeg',
'.m1v': 'video/mpeg',
'.m2v': 'video/mpeg',
'.mpg4': 'video/mp4',
'.mpga': 'audio/mpeg',
'.oga': 'audio/ogg',
'.ogg': 'audio/ogg',
'.ogv': 'video/ogg',
'.png': 'image/png',
'.psd': 'image/vnd.adobe.photoshop',
'.qt': 'video/quicktime',
'.mov': 'video/quicktime',
'.spx': 'audio/ogg',
'.svg': 'image/svg+xml',
'.tga': 'image/x-tga',
'.tif': 'image/tiff',
'.tiff': 'image/tiff',
'.wav': 'audio/x-wav',
'.webm': 'video/webm',
'.mkv': 'video/x-matroska',
'.mk3d': 'video/x-matroska',
'.mks': 'video/x-matroska',
'.webp': 'image/webp',
'.wma': 'audio/x-ms-wma',
'.wmv': 'video/x-ms-wmv',
'.flv': 'video/x-flv',
'.avi': 'video/x-msvideo',
'.movie': 'video/x-sgi-movie'
'.woff': 'application/font-woff',
};
export function getMediaMime(path: string): string | undefined {

View File

@@ -46,4 +46,6 @@ export namespace Schemas {
export const command: string = 'command';
export const vscodeRemote: string = 'vscode-remote';
export const userData: string = 'vscode-userdata';
}

View File

@@ -14,11 +14,11 @@ export function deepClone<T>(obj: T): T {
return obj as any;
}
const result: any = Array.isArray(obj) ? [] : {};
Object.keys(obj as any).forEach((key: string) => {
if (obj[key] && typeof obj[key] === 'object') {
result[key] = deepClone(obj[key]);
Object.keys(<any>obj).forEach((key: string) => {
if ((<any>obj)[key] && typeof (<any>obj)[key] === 'object') {
result[key] = deepClone((<any>obj)[key]);
} else {
result[key] = obj[key];
result[key] = (<any>obj)[key];
}
});
return result;

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as Types from 'vs/base/common/types';
export const enum ValidationState {
OK = 0,
Info = 1,
@@ -78,25 +76,4 @@ export abstract class Parser {
public fatal(message: string): void {
this._problemReporter.fatal(message);
}
protected static merge<T extends object>(destination: T, source: T, overwrite: boolean): void {
Object.keys(source).forEach((key: string) => {
const destValue = destination[key];
const sourceValue = source[key];
if (Types.isUndefined(sourceValue)) {
return;
}
if (Types.isUndefined(destValue)) {
destination[key] = sourceValue;
} else {
if (overwrite) {
if (Types.isObject(destValue) && Types.isObject(sourceValue)) {
this.merge(destValue, sourceValue, overwrite);
} else {
destination[key] = sourceValue;
}
}
}
});
}
}

View File

@@ -212,7 +212,7 @@ export const win32: IPath = {
// absolute path, get cwd for that drive, or the process cwd if
// the drive cwd is not available. We're sure the device is not
// a UNC path at this points, because UNC paths are always absolute.
path = process.env['=' + resolvedDevice] || process.cwd();
path = (process.env as any)['=' + resolvedDevice] || process.cwd();
// Verify that a cwd was found and that it actually points
// to our drive. If not, default to the drive's root.

View File

@@ -221,7 +221,7 @@ export function addTrailingPathSeparator(resource: URI, sep: string = paths.sep)
* Returns a relative path between two URIs. If the URIs don't have the same schema or authority, `undefined` is returned.
* The returned relative path always uses forward slashes.
*/
export function relativePath(from: URI, to: URI): string | undefined {
export function relativePath(from: URI, to: URI, ignoreCase = hasToIgnoreCase(from)): string | undefined {
if (from.scheme !== to.scheme || !isEqualAuthority(from.authority, to.authority)) {
return undefined;
}
@@ -229,7 +229,20 @@ export function relativePath(from: URI, to: URI): string | undefined {
const relativePath = paths.relative(from.path, to.path);
return isWindows ? extpath.toSlashes(relativePath) : relativePath;
}
return paths.posix.relative(from.path || '/', to.path || '/');
let fromPath = from.path || '/', toPath = to.path || '/';
if (ignoreCase) {
// make casing of fromPath match toPath
let i = 0;
for (const len = Math.min(fromPath.length, toPath.length); i < len; i++) {
if (fromPath.charCodeAt(i) !== toPath.charCodeAt(i)) {
if (fromPath.charAt(i).toLowerCase() !== toPath.charAt(i).toLowerCase()) {
break;
}
}
}
fromPath = toPath.substr(0, i) + fromPath.substr(i);
}
return paths.posix.relative(fromPath, toPath);
}
/**

View File

@@ -169,6 +169,31 @@ export function getAllPropertyNames(obj: object): string[] {
return res;
}
export function getAllMethodNames(obj: object): string[] {
const methods: string[] = [];
for (const prop of getAllPropertyNames(obj)) {
if (typeof (obj as any)[prop] === 'function') {
methods.push(prop);
}
}
return methods;
}
export function createProxyObject<T extends object>(methodNames: string[], invoke: (method: string, args: any[]) => any): T {
const createProxyMethod = (method: string): () => any => {
return function () {
const args = Array.prototype.slice.call(arguments, 0);
return invoke(method, args);
};
};
let result = {} as T;
for (const methodName of methodNames) {
(<any>result)[methodName] = createProxyMethod(methodName);
}
return result;
}
/**
* Converts null to undefined, passes all other values through.
*/

View File

@@ -385,8 +385,8 @@ export class URI implements UriComponents {
return data;
} else {
const result = new _URI(data);
result._fsPath = (<UriState>data).fsPath;
result._formatted = (<UriState>data).external;
result._fsPath = (<UriState>data)._sep === _pathSepMarker ? (<UriState>data).fsPath : null;
return result;
}
}
@@ -402,10 +402,12 @@ export interface UriComponents {
interface UriState extends UriComponents {
$mid: number;
fsPath: string;
external: string;
fsPath: string;
_sep: 1 | undefined;
}
const _pathSepMarker = isWindows ? 1 : undefined;
// tslint:disable-next-line:class-name
class _URI extends URI {
@@ -439,6 +441,7 @@ class _URI extends URI {
// cached state
if (this._fsPath) {
res.fsPath = this._fsPath;
res._sep = _pathSepMarker;
}
if (this._formatted) {
res.external = this._formatted;

View File

@@ -10,6 +10,51 @@ export interface IURITransformer {
transformIncoming(uri: UriComponents): UriComponents;
transformOutgoing(uri: UriComponents): UriComponents;
transformOutgoingURI(uri: URI): URI;
transformOutgoingScheme(scheme: string): string;
}
export interface UriParts {
scheme: string;
authority?: string;
path?: string;
}
export interface IRawURITransformer {
transformIncoming(uri: UriParts): UriParts;
transformOutgoing(uri: UriParts): UriParts;
transformOutgoingScheme(scheme: string): string;
}
function toJSON(uri: URI): UriComponents {
return <UriComponents><any>uri.toJSON();
}
export class URITransformer implements IURITransformer {
private readonly _uriTransformer: IRawURITransformer;
constructor(uriTransformer: IRawURITransformer) {
this._uriTransformer = uriTransformer;
}
public transformIncoming(uri: UriComponents): UriComponents {
const result = this._uriTransformer.transformIncoming(uri);
return (result === uri ? uri : toJSON(URI.from(result)));
}
public transformOutgoing(uri: UriComponents): UriComponents {
const result = this._uriTransformer.transformOutgoing(uri);
return (result === uri ? uri : toJSON(URI.from(result)));
}
public transformOutgoingURI(uri: URI): URI {
const result = this._uriTransformer.transformOutgoing(uri);
return (result === uri ? uri : URI.from(result));
}
public transformOutgoingScheme(scheme: string): string {
return this._uriTransformer.transformOutgoingScheme(scheme);
}
}
export const DefaultURITransformer: IURITransformer = new class {
@@ -24,6 +69,10 @@ export const DefaultURITransformer: IURITransformer = new class {
transformOutgoingURI(uri: URI): URI {
return uri;
}
transformOutgoingScheme(scheme: string): string {
return scheme;
}
};
function _transformOutgoingURIs(obj: any, transformer: IURITransformer, depth: number): any {

View File

@@ -4,16 +4,15 @@
*--------------------------------------------------------------------------------------------*/
import { transformErrorForSerialization } from 'vs/base/common/errors';
import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { isWeb } from 'vs/base/common/platform';
import { getAllPropertyNames } from 'vs/base/common/types';
import * as types from 'vs/base/common/types';
const INITIALIZE = '$initialize';
export interface IWorker {
export interface IWorker extends IDisposable {
getId(): number;
postMessage(message: string): void;
dispose(): void;
}
export interface IWorkerCallback {
@@ -174,17 +173,22 @@ class SimpleWorkerProtocol {
}
}
export interface IWorkerClient<W> {
getProxyObject(): Promise<W>;
dispose(): void;
}
/**
* Main thread side
*/
export class SimpleWorkerClient<T> extends Disposable {
export class SimpleWorkerClient<W extends object, H extends object> extends Disposable implements IWorkerClient<W> {
private _worker: IWorker;
private _onModuleLoaded: Promise<string[]>;
private _protocol: SimpleWorkerProtocol;
private _lazyProxy: Promise<T>;
private readonly _worker: IWorker;
private readonly _onModuleLoaded: Promise<string[]>;
private readonly _protocol: SimpleWorkerProtocol;
private readonly _lazyProxy: Promise<W>;
constructor(workerFactory: IWorkerFactory, moduleId: string) {
constructor(workerFactory: IWorkerFactory, moduleId: string, host: H) {
super();
let lazyProxyReject: ((err: any) => void) | null = null;
@@ -208,8 +212,15 @@ export class SimpleWorkerClient<T> extends Disposable {
this._worker.postMessage(msg);
},
handleMessage: (method: string, args: any[]): Promise<any> => {
// Intentionally not supporting worker -> main requests
return Promise.resolve(null);
if (typeof (host as any)[method] !== 'function') {
return Promise.reject(new Error('Missing method ' + method + ' on main thread host.'));
}
try {
return Promise.resolve((host as any)[method].apply(host, args));
} catch (e) {
return Promise.reject(e);
}
}
});
this._protocol.setWorkerId(this._worker.getId());
@@ -224,41 +235,33 @@ export class SimpleWorkerClient<T> extends Disposable {
loaderConfiguration = (<any>self).requirejs.s.contexts._.config;
}
const hostMethods = types.getAllMethodNames(host);
// Send initialize message
this._onModuleLoaded = this._protocol.sendMessage(INITIALIZE, [
this._worker.getId(),
loaderConfiguration,
moduleId,
loaderConfiguration
hostMethods,
]);
this._lazyProxy = new Promise<T>((resolve, reject) => {
lazyProxyReject = reject;
this._onModuleLoaded.then((availableMethods: string[]) => {
let proxy = <T>{};
for (const methodName of availableMethods) {
(proxy as any)[methodName] = createProxyMethod(methodName, proxyMethodRequest);
}
resolve(proxy);
}, (e) => {
reject(e);
this._onError('Worker failed to load ' + moduleId, e);
});
});
// Create proxy to loaded code
const proxyMethodRequest = (method: string, args: any[]): Promise<any> => {
return this._request(method, args);
};
const createProxyMethod = (method: string, proxyMethodRequest: (method: string, args: any[]) => Promise<any>): () => Promise<any> => {
return function () {
let args = Array.prototype.slice.call(arguments, 0);
return proxyMethodRequest(method, args);
};
};
this._lazyProxy = new Promise<W>((resolve, reject) => {
lazyProxyReject = reject;
this._onModuleLoaded.then((availableMethods: string[]) => {
resolve(types.createProxyObject<W>(availableMethods, proxyMethodRequest));
}, (e) => {
reject(e);
this._onError('Worker failed to load ' + moduleId, e);
});
});
}
public getProxyObject(): Promise<T> {
public getProxyObject(): Promise<W> {
return this._lazyProxy;
}
@@ -281,16 +284,22 @@ export interface IRequestHandler {
[prop: string]: any;
}
export interface IRequestHandlerFactory<H> {
(host: H): IRequestHandler;
}
/**
* Worker side
*/
export class SimpleWorkerServer {
export class SimpleWorkerServer<H extends object> {
private _requestHandlerFactory: IRequestHandlerFactory<H> | null;
private _requestHandler: IRequestHandler | null;
private _protocol: SimpleWorkerProtocol;
constructor(postSerializedMessage: (msg: string) => void, requestHandler: IRequestHandler | null) {
this._requestHandler = requestHandler;
constructor(postSerializedMessage: (msg: string) => void, requestHandlerFactory: IRequestHandlerFactory<H> | null) {
this._requestHandlerFactory = requestHandlerFactory;
this._requestHandler = null;
this._protocol = new SimpleWorkerProtocol({
sendMessage: (msg: string): void => {
postSerializedMessage(msg);
@@ -305,7 +314,7 @@ export class SimpleWorkerServer {
private _handleMessage(method: string, args: any[]): Promise<any> {
if (method === INITIALIZE) {
return this.initialize(<number>args[0], <string>args[1], <any>args[2]);
return this.initialize(<number>args[0], <any>args[1], <string>args[2], <string[]>args[3]);
}
if (!this._requestHandler || typeof this._requestHandler[method] !== 'function') {
@@ -319,18 +328,19 @@ export class SimpleWorkerServer {
}
}
private initialize(workerId: number, moduleId: string, loaderConfig: any): Promise<string[]> {
private initialize(workerId: number, loaderConfig: any, moduleId: string, hostMethods: string[]): Promise<string[]> {
this._protocol.setWorkerId(workerId);
if (this._requestHandler) {
const proxyMethodRequest = (method: string, args: any[]): Promise<any> => {
return this._protocol.sendMessage(method, args);
};
const hostProxy = types.createProxyObject<H>(hostMethods, proxyMethodRequest);
if (this._requestHandlerFactory) {
// static request handler
let methods: string[] = [];
for (const prop of getAllPropertyNames(this._requestHandler)) {
if (typeof this._requestHandler[prop] === 'function') {
methods.push(prop);
}
}
return Promise.resolve(methods);
this._requestHandler = this._requestHandlerFactory(hostProxy);
return Promise.resolve(types.getAllMethodNames(this._requestHandler));
}
if (loaderConfig) {
@@ -351,23 +361,15 @@ export class SimpleWorkerServer {
return new Promise<string[]>((resolve, reject) => {
// Use the global require to be sure to get the global config
(<any>self).require([moduleId], (...result: any[]) => {
let handlerModule = result[0];
this._requestHandler = handlerModule.create();
(<any>self).require([moduleId], (module: { create: IRequestHandlerFactory<H> }) => {
this._requestHandler = module.create(hostProxy);
if (!this._requestHandler) {
reject(new Error(`No RequestHandler!`));
return;
}
let methods: string[] = [];
for (const prop of getAllPropertyNames(this._requestHandler)) {
if (typeof this._requestHandler[prop] === 'function') {
methods.push(prop);
}
}
resolve(methods);
resolve(types.getAllMethodNames(this._requestHandler));
}, reject);
});
}
@@ -376,6 +378,6 @@ export class SimpleWorkerServer {
/**
* Called on the worker side
*/
export function create(postMessage: (msg: string) => void): SimpleWorkerServer {
export function create(postMessage: (msg: string) => void): SimpleWorkerServer<any> {
return new SimpleWorkerServer(postMessage, null);
}