Merge from master

This commit is contained in:
Raj Musuku
2019-02-21 17:56:04 -08:00
parent 5a146e34fa
commit 666ae11639
11482 changed files with 119352 additions and 255574 deletions

View File

@@ -2,27 +2,31 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as platform from 'vs/base/common/platform';
import { TPromise } from 'vs/base/common/winjs.base';
import { TimeoutTimer } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import * as browser from 'vs/base/browser/browser';
import { domEvent } from 'vs/base/browser/event';
import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { TimeoutTimer } from 'vs/base/common/async';
import { CharCode } from 'vs/base/common/charCode';
import { Event, Emitter } from 'vs/base/common/event';
import { domEvent } from 'vs/base/browser/event';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';
export function clearNode(node: HTMLElement) {
export function clearNode(node: HTMLElement): void {
while (node.firstChild) {
node.removeChild(node.firstChild);
}
}
export function isInDOM(node: Node): boolean {
export function removeNode(node: HTMLElement): void {
if (node.parentNode) {
node.parentNode.removeChild(node);
}
}
export function isInDOM(node: Node | null): boolean {
while (node) {
if (node === document.body) {
return true;
@@ -153,7 +157,7 @@ const _manualClassList = new class implements IDomClassList {
const _nativeClassList = new class implements IDomClassList {
hasClass(node: HTMLElement, className: string): boolean {
return className && node.classList && node.classList.contains(className);
return Boolean(className) && node.classList && node.classList.contains(className);
}
addClasses(node: HTMLElement, ...classNames: string[]): void {
@@ -200,7 +204,7 @@ class DomListener implements IDisposable {
private readonly _type: string;
private readonly _useCapture: boolean;
constructor(node: Element | Window | Document, type: string, handler: (e: any) => void, useCapture: boolean) {
constructor(node: Element | Window | Document, type: string, handler: (e: any) => void, useCapture?: boolean) {
this._node = node;
this._type = type;
this._handler = handler;
@@ -217,11 +221,13 @@ class DomListener implements IDisposable {
this._node.removeEventListener(this._type, this._handler, this._useCapture);
// Prevent leakers from holding on to the dom or handler func
this._node = null;
this._handler = null;
this._node = null!;
this._handler = null!;
}
}
export function addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(node: Element | Window | Document, type: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, useCapture?: boolean): IDisposable;
export function addDisposableListener(node: Element | Window | Document, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable;
export function addDisposableListener(node: Element | Window | Document, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable {
return new DomListener(node, type, handler, useCapture);
}
@@ -259,7 +265,7 @@ export let addStandardDisposableListener: IAddStandardDisposableListenerSignatur
export function addDisposableNonBubblingMouseOutListener(node: Element, handler: (event: MouseEvent) => void): IDisposable {
return addDisposableListener(node, 'mouseout', (e: MouseEvent) => {
// Mouse out bubbles, so this is an attempt to ignore faux mouse outs coming from children elements
let toElement = <Node>(e.relatedTarget || e.toElement);
let toElement: Node | null = <Node>(e.relatedTarget || e.toElement);
while (toElement && toElement !== node) {
toElement = toElement.parentNode;
}
@@ -274,10 +280,10 @@ export function addDisposableNonBubblingMouseOutListener(node: Element, handler:
interface IRequestAnimationFrame {
(callback: (time: number) => void): number;
}
let _animationFrame: IRequestAnimationFrame = null;
let _animationFrame: IRequestAnimationFrame | null = null;
function doRequestAnimationFrame(callback: (time: number) => void): number {
if (!_animationFrame) {
const emulatedRequestAnimationFrame = (callback: (time: number) => void): number => {
const emulatedRequestAnimationFrame = (callback: (time: number) => void): any => {
return setTimeout(() => callback(new Date().getTime()), 0);
};
_animationFrame = (
@@ -313,7 +319,7 @@ class AnimationFrameQueueItem implements IDisposable {
public priority: number;
private _canceled: boolean;
constructor(runner: () => void, priority: number) {
constructor(runner: () => void, priority: number = 0) {
this._runner = runner;
this.priority = priority;
this._canceled = false;
@@ -349,7 +355,7 @@ class AnimationFrameQueueItem implements IDisposable {
/**
* The runners scheduled at the current animation frame
*/
let CURRENT_QUEUE: AnimationFrameQueueItem[] = null;
let CURRENT_QUEUE: AnimationFrameQueueItem[] | null = null;
/**
* A flag to keep track if the native requestAnimationFrame was already called
*/
@@ -368,7 +374,7 @@ class AnimationFrameQueueItem implements IDisposable {
inAnimationFrameRunner = true;
while (CURRENT_QUEUE.length > 0) {
CURRENT_QUEUE.sort(AnimationFrameQueueItem.sort);
let top = CURRENT_QUEUE.shift();
let top = CURRENT_QUEUE.shift()!;
top.execute();
}
inAnimationFrameRunner = false;
@@ -389,7 +395,7 @@ class AnimationFrameQueueItem implements IDisposable {
runAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, priority?: number) => {
if (inAnimationFrameRunner) {
let item = new AnimationFrameQueueItem(runner, priority);
CURRENT_QUEUE.push(item);
CURRENT_QUEUE!.push(item);
return item;
} else {
return scheduleAtNextAnimationFrame(runner, priority);
@@ -397,11 +403,19 @@ class AnimationFrameQueueItem implements IDisposable {
};
})();
export function measure(callback: () => void): IDisposable {
return scheduleAtNextAnimationFrame(callback, 10000 /* must be early */);
}
export function modify(callback: () => void): IDisposable {
return scheduleAtNextAnimationFrame(callback, -10000 /* must be late */);
}
/**
* Add a throttled listener. `handler` is fired at most every 16ms or with the next animation frame (if browser supports it).
*/
export interface IEventMerger<R, E> {
(lastEvent: R, currentEvent: E): R;
(lastEvent: R | null, currentEvent: E): R;
}
export interface DOMEvent {
@@ -419,13 +433,13 @@ class TimeoutThrottledDomListener<R, E extends DOMEvent> extends Disposable {
constructor(node: any, type: string, handler: (event: R) => void, eventMerger: IEventMerger<R, E> = <any>DEFAULT_EVENT_MERGER, minimumTimeMs: number = MINIMUM_TIME_MS) {
super();
let lastEvent: R = null;
let lastEvent: R | null = null;
let lastHandlerTime = 0;
let timeout = this._register(new TimeoutTimer());
let invokeHandler = () => {
lastHandlerTime = (new Date()).getTime();
handler(lastEvent);
handler(<R>lastEvent);
lastEvent = null;
};
@@ -449,7 +463,7 @@ export function addDisposableThrottledListener<R, E extends DOMEvent = DOMEvent>
}
export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration {
return document.defaultView.getComputedStyle(el, null);
return document.defaultView!.getComputedStyle(el, null);
}
// Adapted from WinJS
@@ -486,8 +500,8 @@ export function getClientArea(element: HTMLElement): Dimension {
return new Dimension(window.innerWidth, window.innerHeight);
}
// Try with document.body.clientWidth / document.body.clientHeigh
if (document.body && document.body.clientWidth && document.body.clientWidth) {
// Try with document.body.clientWidth / document.body.clientHeight
if (document.body && document.body.clientWidth && document.body.clientHeight) {
return new Dimension(document.body.clientWidth, document.body.clientHeight);
}
@@ -553,6 +567,16 @@ export class Dimension {
this.width = width;
this.height = height;
}
static equals(a: Dimension | undefined, b: Dimension | undefined): boolean {
if (a === b) {
return true;
}
if (!a || !b) {
return false;
}
return a.width === b.width && a.height === b.height;
}
}
export function getTopLeftOffset(element: HTMLElement): { left: number; top: number; } {
@@ -644,7 +668,7 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin
// modern browsers
return window.scrollX;
} else {
return document.body.scrollLeft + document.documentElement.scrollLeft;
return document.body.scrollLeft + document.documentElement!.scrollLeft;
}
}
@@ -653,7 +677,7 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin
// modern browsers
return window.scrollY;
} else {
return document.body.scrollTop + document.documentElement.scrollTop;
return document.body.scrollTop + document.documentElement!.scrollTop;
}
}
};
@@ -712,7 +736,7 @@ export function getLargestChildWidth(parent: HTMLElement, children: HTMLElement[
// ----------------------------------------------------------------------------------------
export function isAncestor(testChild: Node, testAncestor: Node): boolean {
export function isAncestor(testChild: Node | null, testAncestor: Node | null): boolean {
while (testChild) {
if (testChild === testAncestor) {
return true;
@@ -723,7 +747,7 @@ export function isAncestor(testChild: Node, testAncestor: Node): boolean {
return false;
}
export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement {
export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement | null {
while (node) {
if (hasClass(node, clazz)) {
return node;
@@ -755,7 +779,7 @@ export function createStyleSheet(container: HTMLElement = document.getElementsBy
return style;
}
let _sharedStyleSheet: HTMLStyleElement = null;
let _sharedStyleSheet: HTMLStyleElement | null = null;
function getSharedStyleSheet(): HTMLStyleElement {
if (!_sharedStyleSheet) {
_sharedStyleSheet = createStyleSheet();
@@ -811,49 +835,48 @@ export function isHTMLElement(o: any): o is HTMLElement {
export const EventType = {
// Mouse
CLICK: 'click',
AUXCLICK: 'auxclick', // >= Chrome 56
DBLCLICK: 'dblclick',
MOUSE_UP: 'mouseup',
MOUSE_DOWN: 'mousedown',
MOUSE_OVER: 'mouseover',
MOUSE_MOVE: 'mousemove',
MOUSE_OUT: 'mouseout',
MOUSE_ENTER: 'mouseenter',
MOUSE_LEAVE: 'mouseleave',
CONTEXT_MENU: 'contextmenu',
WHEEL: 'wheel',
CLICK: 'click' as 'click',
DBLCLICK: 'dblclick' as 'dblclick',
MOUSE_UP: 'mouseup' as 'mouseup',
MOUSE_DOWN: 'mousedown' as 'mousedown',
MOUSE_OVER: 'mouseover' as 'mouseover',
MOUSE_MOVE: 'mousemove' as 'mousemove',
MOUSE_OUT: 'mouseout' as 'mouseout',
MOUSE_ENTER: 'mouseenter' as 'mouseenter',
MOUSE_LEAVE: 'mouseleave' as 'mouseleave',
CONTEXT_MENU: 'contextmenu' as 'contextmenu',
WHEEL: 'wheel' as 'wheel',
// Keyboard
KEY_DOWN: 'keydown',
KEY_PRESS: 'keypress',
KEY_UP: 'keyup',
KEY_DOWN: 'keydown' as 'keydown',
KEY_PRESS: 'keypress' as 'keypress',
KEY_UP: 'keyup' as 'keyup',
// HTML Document
LOAD: 'load',
UNLOAD: 'unload',
ABORT: 'abort',
ERROR: 'error',
RESIZE: 'resize',
SCROLL: 'scroll',
LOAD: 'load' as 'load',
UNLOAD: 'unload' as 'unload',
ABORT: 'abort' as 'abort',
ERROR: 'error' as 'error',
RESIZE: 'resize' as 'resize',
SCROLL: 'scroll' as 'scroll',
// Form
SELECT: 'select',
CHANGE: 'change',
SUBMIT: 'submit',
RESET: 'reset',
FOCUS: 'focus',
FOCUS_IN: 'focusin',
FOCUS_OUT: 'focusout',
BLUR: 'blur',
INPUT: 'input',
SELECT: 'select' as 'select',
CHANGE: 'change' as 'change',
SUBMIT: 'submit' as 'submit',
RESET: 'reset' as 'reset',
FOCUS: 'focus' as 'focus',
FOCUS_IN: 'focusin' as 'focusin',
FOCUS_OUT: 'focusout' as 'focusout',
BLUR: 'blur' as 'blur',
INPUT: 'input' as 'input',
// Local Storage
STORAGE: 'storage',
STORAGE: 'storage' as 'storage',
// Drag
DRAG_START: 'dragstart',
DRAG: 'drag',
DRAG_ENTER: 'dragenter',
DRAG_LEAVE: 'dragleave',
DRAG_OVER: 'dragover',
DROP: 'drop',
DRAG_END: 'dragend',
DRAG_START: 'dragstart' as 'dragstart',
DRAG: 'drag' as 'drag',
DRAG_ENTER: 'dragenter' as 'dragenter',
DRAG_LEAVE: 'dragleave' as 'dragleave',
DRAG_OVER: 'dragover' as 'dragover',
DROP: 'drop' as 'drop',
DRAG_END: 'dragend' as 'dragend',
// Animation
ANIMATION_START: browser.isWebKit ? 'webkitAnimationStart' : 'animationstart',
ANIMATION_END: browser.isWebKit ? 'webkitAnimationEnd' : 'animationend',
@@ -920,7 +943,7 @@ class FocusTracker implements IFocusTracker {
private disposables: IDisposable[] = [];
constructor(element: HTMLElement | Window) {
let hasFocus = false;
let hasFocus = isAncestor(document.activeElement, <HTMLElement>element);
let loosingFocus = false;
let onFocus = () => {
@@ -971,7 +994,6 @@ export function prepend<T extends Node>(parent: HTMLElement, child: T): T {
const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((.([\w\-]+))*)/;
// Similar to builder, but much more lightweight
export function $<T extends HTMLElement>(description: string, attrs?: { [key: string]: any; }, ...children: (Node | string)[]): T {
let match = SELECTOR_REGEX.exec(description);
@@ -988,17 +1010,18 @@ export function $<T extends HTMLElement>(description: string, attrs?: { [key: st
result.className = match[4].replace(/\./g, ' ').trim();
}
Object.keys(attrs || {}).forEach(name => {
attrs = attrs || {};
Object.keys(attrs).forEach(name => {
const value = attrs![name];
if (/^on\w+$/.test(name)) {
(<any>result)[name] = attrs[name];
(<any>result)[name] = value;
} else if (name === 'selected') {
const value = attrs[name];
if (value) {
result.setAttribute(name, 'true');
}
} else {
result.setAttribute(name, attrs[name]);
result.setAttribute(name, value);
}
});
@@ -1047,7 +1070,7 @@ export function hide(...elements: HTMLElement[]): void {
}
}
function findParentWithAttribute(node: Node, attribute: string): HTMLElement {
function findParentWithAttribute(node: Node | null, attribute: string): HTMLElement | null {
while (node) {
if (node instanceof HTMLElement && node.hasAttribute(attribute)) {
return node;
@@ -1090,13 +1113,13 @@ export function finalHandler<T extends DOMEvent>(fn: (event: T) => any): (event:
};
}
export function domContentLoaded(): TPromise<any> {
return new TPromise<any>((c, e) => {
export function domContentLoaded(): Promise<any> {
return new Promise<any>(resolve => {
const readyState = document.readyState;
if (readyState === 'complete' || (document && document.body !== null)) {
platform.setImmediate(c);
platform.setImmediate(resolve);
} else {
window.addEventListener('DOMContentLoaded', c, false);
window.addEventListener('DOMContentLoaded', resolve, false);
}
});
}