From 217de70449c7870057d440d161752f1945dc4937 Mon Sep 17 00:00:00 2001 From: christopherthielen Date: Thu, 18 Feb 2016 18:38:16 -0600 Subject: [PATCH] feat(ui-router-ng2): Initial angular2 support --- Gruntfile.js | 40 +- files.js | 6 +- package.json | 10 +- src/justjs.ts | 10 +- src/ng2.ts | 12 + src/ng2/uiSref.ts | 53 +++ src/ng2/uiSrefActive.ts | 51 +++ src/ng2/uiView.ts | 121 ++++++ src/path/node.ts | 3 +- src/state/interface.ts | 10 + src/view/view.ts | 5 +- test/viewSpec.ts | 3 +- tsconfig-ng2.json | 19 + tsconfig.json | 16 + tsd.json | 8 + typings/es6-shim/es6-shim.d.ts | 668 +++++++++++++++++++++++++++++++++ 16 files changed, 1008 insertions(+), 27 deletions(-) create mode 100644 src/ng2.ts create mode 100644 src/ng2/uiSref.ts create mode 100644 src/ng2/uiSrefActive.ts create mode 100755 src/ng2/uiView.ts create mode 100644 tsconfig-ng2.json create mode 100644 tsconfig.json create mode 100644 tsd.json create mode 100644 typings/es6-shim/es6-shim.d.ts diff --git a/Gruntfile.js b/Gruntfile.js index 3dedc386e..e8e81796d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -21,16 +21,8 @@ module.exports = function (grunt) { }, clean: [ '<%= builddir %>' ], ts: { - es5: { - src: files.src, - outDir: '<%= builddir %>/es5', - options: { module: 'commonjs'} - }, - es6: { - src: files.src, - outDir: '<%= builddir %>/es6', - options: { target: "es6"} - } + ng1: { tsconfig: 'tsconfig.json' }, + ng2: { tsconfig: 'tsconfig-ng2.json' } }, uglify: { options: { @@ -39,7 +31,7 @@ module.exports = function (grunt) { }, build: { files: { - '<%= builddir %>/ui-router.min.js': ['', '<%= builddir %>/ui-router.js'], + '<%= builddir %>/ui-router-ng2.min.js': ['', '<%= builddir %>/ui-router-ng2.js'], '<%= builddir %>/<%= pkg.name %>.min.js': ['', '<%= builddir %>/<%= pkg.name %>.js'], '<%= builddir %>/ng1/stateEvents.min.js': ['', '<%= builddir %>/ng1/stateEvents.js'] } @@ -67,18 +59,34 @@ module.exports = function (grunt) { } ] }, - core: { - entry: files.justjsCommonJsEntrypoint, + ng2: { + entry: files.ng2CommonJsEntrypoint, output: { path: '<%= builddir %>', - filename: 'ui-router-justjs.js', + filename: 'ui-router-ng2.js', library: 'uiRouter', libraryTarget: 'umd' }, module: { loaders: [] - } + }, + externals: [{ + 'angular2/core': {root: ['ng', 'core'], commonjs: 'angular2/core', commonjs2: 'angular2/core', amd: 'angular2/core'}, + 'angular2/common': {root: ['ng', 'common'], commonjs: 'angular2/common', commonjs2: 'angular2/common', amd: 'angular2/common'} + }] } + //,core: { + // entry: files.justjsCommonJsEntrypoint, + // output: { + // path: '<%= builddir %>', + // filename: 'ui-router-justjs.js', + // library: 'uiRouter', + // libraryTarget: 'umd' + // }, + // module: { + // loaders: [] + // } + //} }, release: { files: ['<%= pkg.name %>.js', '<%= pkg.name %>.min.js'], @@ -164,7 +172,7 @@ module.exports = function (grunt) { grunt.registerTask('integrate', ['clean', 'build', 'karma:ng12', 'karma:ng13', 'karma:ng14', 'karma:ng15']); grunt.registerTask('default', ['build', 'karma:unit', 'docs']); - grunt.registerTask('build', 'Perform a normal build', ['clean', 'ts', 'webpack', 'bundles', 'uglify']); + grunt.registerTask('build', 'Perform a normal build', ['clean', 'ts', 'bundles', 'uglify']); grunt.registerTask('dist-docs', 'Perform a clean build and generate documentation', ['build', 'ngdocs']); grunt.registerTask('release', 'Tag and perform a release', ['prepare-release', 'build', 'perform-release']); grunt.registerTask('dev', 'Run dev server and watch for changes', ['build', 'connect:server', 'karma:background', 'watch']); diff --git a/files.js b/files.js index edcd24bf9..6ee6bf1b9 100644 --- a/files.js +++ b/files.js @@ -1,13 +1,15 @@ routerFiles = { ng1CommonJsEntrypoint: ['./build/es5/ng1.js'], + ng2CommonJsEntrypoint: ['./build/es5/ng2.js'], justjsCommonJsEntrypoint: ['./build/es5/justjs.js'], // es6Entrypoint: ['./build/es6/ng1.js'], src: [ - 'src/ui-router.ts', // Main UI-Router module (re-exports all other core modules) 'src/ng1.ts', // UI-Router angular1 module (re-exports ui-router and ng1 modules) - 'src/justjs.ts', // UI-Router plain ol js module (re-exports ui-router) 'src/ng1/stateEvents.ts' // There might be a better approach to compiling this file + //'src/ui-router.ts', // Main UI-Router module (re-exports all other core modules) + //'src/ng2.ts', // UI-Router angular2 module (re-exports ui-router and ng2 modules) + //'src/justjs.ts', // UI-Router plain ol js module (re-exports ui-router) ], // Test helpers diff --git a/package.json b/package.json index 96155d6a3..e76f942b5 100644 --- a/package.json +++ b/package.json @@ -51,8 +51,11 @@ "angular": "^1.2" }, "devDependencies": { + "angular2": "^2.0.0-beta.1", "babel-core": "^5.8.14", "es6-module-loader": "^0.17.3", + "es6-promise": "^3.0.2", + "es6-shim": "^0.33.13", "faithful-exec": "~0.1.0", "grunt": "~0.4.1", "grunt-contrib-clean": "~0.5.0", @@ -63,7 +66,7 @@ "grunt-karma": "~0.11.2", "grunt-ngdocs": "~0.1.7", "grunt-shell": "^1.1.2", - "grunt-ts": "^4.2.0", + "grunt-ts": "^5.2.0", "grunt-webpack": "^1.0.10", "jasmine-core": "~2.3.4", "jsdoc": "git://github.com/jsdoc3/jsdoc.git#v3.2.2", @@ -75,13 +78,16 @@ "karma-systemjs": "^0.7.2", "load-grunt-tasks": "~0.4.0", "phantomjs-polyfill": "0.0.1", + "reflect-metadata": "^0.1.2", + "rxjs": "^5.0.0-beta.0", "shelljs": "~0.2.6", "systemjs": "^0.18.4", "tslint": "=2.5.0", "typedoc": "git://github.com/christopherthielen/typedoc.git#v0.3-uirouter", "typescript": "=1.7.3", "webpack": "1.x", - "webpack-dev-server": "1.x" + "webpack-dev-server": "1.x", + "zone.js": "^0.5.10" }, "main": "release/angular-ui-router.js" } diff --git a/src/justjs.ts b/src/justjs.ts index 6434c7c51..f48dff278 100644 --- a/src/justjs.ts +++ b/src/justjs.ts @@ -1,5 +1,3 @@ -/// - export * from "./ui-router"; import {services} from "./common/coreservices"; import {isDefined, isFunction, isArray, isObject, isInjectable} from "./common/predicates"; @@ -87,3 +85,11 @@ loc.onChange = (cb) => { window.addEventListener("hashchange", cb, false); }; +let locCfg = services.locationConfig; + +locCfg.port = () => location.port; +locCfg.protocol = () => location.protocol; +locCfg.host = () => location.host; +locCfg.baseHref = () => ""; +locCfg.html5Mode = () => false; +locCfg.hashPrefix = () => ""; diff --git a/src/ng2.ts b/src/ng2.ts new file mode 100644 index 000000000..e1d863386 --- /dev/null +++ b/src/ng2.ts @@ -0,0 +1,12 @@ +/// +/** + * Main entry point for angular 2.x build + */ +/** for typedoc */ + +export * from "./ui-router"; +import "./justjs"; +export * from "./ng2/uiView"; +export * from "./ng2/uiSref"; +export * from "./ng2/uiSrefActive"; + diff --git a/src/ng2/uiSref.ts b/src/ng2/uiSref.ts new file mode 100644 index 000000000..da6da5969 --- /dev/null +++ b/src/ng2/uiSref.ts @@ -0,0 +1,53 @@ +import {UIRouter} from "../router"; +import {Directive} from "angular2/core"; +import {Optional} from "angular2/core"; +import {Input} from "angular2/core"; +import {ElementRef} from "angular2/core"; +import {Renderer} from "angular2/core"; + +@Directive({ selector: 'a[uiSref]' }) +export class AnchorUiSref { + constructor( public _el: ElementRef, public _renderer: Renderer) { } + update(href) { + this._renderer.setElementProperty(this._el, 'href', href); + } +} + +@Directive({ + selector: '[uiSref]', + inputs: ['uiSref', 'uiParams', 'uiOptions'], + host: { '(click)': 'go()' } +}) +export class UiSref { + state: string; + params: any; + options: any; + + constructor( + private _router: UIRouter, + @Optional() private _anchorUiSref: AnchorUiSref + ) { } + + set "ui-sref"(val) { this.state = val; this.update(); } + set "uiSref"(val) { this.state = val; this.update(); } + set "uiParams"(val) { this.params = val; this.update(); } + set "uiOptions"(val) { this.options = val; this.update(); } + + ngOnInit() { + this.update(); + } + + update() { + if (this._anchorUiSref) { + this._anchorUiSref.update(this._router.stateService.href(this.state, this.params)); + } + // TODO: process ui-sref-active + } + + go() { + this._router.stateService.go(this.state, this.params, this.options); + return false; + } +} + + diff --git a/src/ng2/uiSrefActive.ts b/src/ng2/uiSrefActive.ts new file mode 100644 index 000000000..bcc4f76e5 --- /dev/null +++ b/src/ng2/uiSrefActive.ts @@ -0,0 +1,51 @@ +import {UIRouter} from "../router"; +import {Directive} from "angular2/core"; +import {UiSref} from "./uiSref"; + +@Directive({ + selector: '[uiSrefClass]', + inputs: ['uiSrefClass'] +}) +export class UiSrefClass { + // current statuses of the bound uiSref directive + active = false; + exact = false; + entering = false; + exiting = false; + inactive = true; + + patterns: any; + classes: string; + sref: UiSref; + + //constructor($transitions: TransitionService, public router: UIRouter) { + constructor(public router: UIRouter) { + this.ngOnDestroy = router.transitionService.onSuccess({}, this._update.bind(this)); + } + + ngOnDestroy() {} + + /** + * e.g. + * { + * active: 'active && !exiting', + * loading: 'entering', + * active: matches('admin.*') + * } + */ + set uiSrefClass(val) { + console.log(val); // [uiSrefClass]="{active: isActive}" logs as "{active: undefined}" + this.patterns = val; + } + + public provideUiSref(sref: UiSref) { + this.sref = sref; + this._update(); + } + + private _update() { + if (!this.sref) return; + // update classes + } +} + diff --git a/src/ng2/uiView.ts b/src/ng2/uiView.ts new file mode 100755 index 000000000..c44cce8b0 --- /dev/null +++ b/src/ng2/uiView.ts @@ -0,0 +1,121 @@ +import {Component, ElementRef, DynamicComponentLoader} from 'angular2/core'; +import {Injector} from "angular2/core"; +import {provide} from "angular2/core"; +import {Input} from "angular2/core"; +import {ComponentRef} from "angular2/core"; +import {Type} from "angular2/core"; + +import {UIRouter} from "../router"; +import {trace} from "../common/trace"; +import {ViewConfig} from "../view/view"; +import {Inject} from "angular2/core"; +import {ViewContext} from "../view/interface"; + +let id = 0; + +const getProviders = (injector) => { + let providers = [], parentInj = injector.parent; + for (let i = 0; i < parentInj._proto.numberOfProviders; i++) { + providers.push(parentInj._proto.getProviderAtIndex(i)); + } + return providers; +}; + +@Component({ + selector: 'ui-view, [ui-view]', + styles: [` + .done-true { + text-decoration: line-through; + color: grey; + }` + ], + template: ` +
+ +
+
ui-view #{{uiViewData.id}} created by '{{ parentContext.name || "(root)" }}' state
+
name: (absolute) '{{uiViewData.fqn}}' (contextual) '{{uiViewData.name}}@{{parentContext.name}}'
+
currently filled by: '{{(uiViewData.config && uiViewData.config.context) || 'empty...'}}' +
+ +
+ ` +}) +export class UiView { + @Input() name: string; + @Input() set 'ui-view'(val) { this.name = val; } + + componentRef: ComponentRef; + deregister: Function; + uiViewData: any = {}; + + static INJECT = { + fqn: "UiView.parentFQN", + context: "UiView.parentContext" + }; + + constructor( + public router: UIRouter, + @Inject(UiView.INJECT.context) public parentContext: ViewContext, + @Inject(UiView.INJECT.fqn) public parentFqn: string, + public dcl: DynamicComponentLoader, + public elementRef: ElementRef, + public injector: Injector + ) { } + + ngOnInit() { + let parentFqn = this.parentFqn; + let name = this.name || '$default'; + console.log(`parentFqn: ${parentFqn}`); + + this.uiViewData = { + id: id++, + name: name, + fqn: parentFqn ? parentFqn + "." + name : name, + creationContext: this.parentContext, + configUpdated: this.viewConfigUpdated.bind(this), + config: undefined + }; + + this.deregister = this.router.viewService.registerUiView(this.uiViewData); + } + + disposeLast() { + if (this.componentRef) this.componentRef.dispose(); + } + + ngOnDestroy() { + this.deregister(); + this.disposeLast(); + } + + viewConfigUpdated(config: ViewConfig) { + let {uiViewData, injector, dcl, elementRef} = this; + + // The "new" viewconfig is already applied, so exit early + if (uiViewData.config === config) return; + // This is a new viewconfig. Destroy the old component + this.disposeLast(); + trace.traceUiViewConfigUpdated(uiViewData, config && config.context); + uiViewData.config = config; + // The config may be undefined if there is nothing state currently targeting this UiView. + if (!config) return; + + // Do some magic + let rc = config.node.resolveContext; + let resolvables = rc.getResolvables(); + let rawProviders = Object.keys(resolvables).map(key => provide(key, { useValue: resolvables[key].data })); + rawProviders.push(provide(UiView.INJECT.context, { useValue: config.context })); + rawProviders.push(provide(UiView.INJECT.fqn, { useValue: uiViewData.fqn })); + let providers = Injector.resolve(rawProviders); + + let exclusions = [UiView.INJECT.context, UiView.INJECT.fqn]; + providers = getProviders(injector).filter(x => exclusions.indexOf(x.key.displayName) === -1).concat(providers); + + // The 'controller' should be a Component class + // TODO: pull from 'component' declaration, do not require template. + let component = config.viewDeclarationObj.controller; + dcl.loadIntoLocation(component, elementRef, "content", providers).then(ref => this.componentRef = ref); + } +} + diff --git a/src/path/node.ts b/src/path/node.ts index d09034f56..72d12225d 100644 --- a/src/path/node.ts +++ b/src/path/node.ts @@ -1,5 +1,4 @@ /** @module path */ /** for typedoc */ -/// import {extend, applyPairs, map, find, allTrueR, values} from "../common/common"; import {prop, propEq} from "../common/hof"; import {State} from "../state/module"; @@ -28,7 +27,7 @@ export class Node { this.resolves = extend(map(state.resolve, (fn: Function, name: string) => new Resolvable(name, fn)), resolves); const makeViewConfig = (viewDeclarationObj, rawViewName) => - new ViewConfig({ rawViewName, viewDeclarationObj, context: state, params}); + new ViewConfig({ rawViewName, viewDeclarationObj, context: state, params, node: this}); this.views = values(map(state.views, makeViewConfig)); } diff --git a/src/state/interface.ts b/src/state/interface.ts index d2c81a3e1..0cc20a792 100644 --- a/src/state/interface.ts +++ b/src/state/interface.ts @@ -2,6 +2,7 @@ import {TransitionOptions} from "../transition/interface"; import {ParamDeclaration, RawParams, ParamsOrArray} from "../params/interface"; +import {Node} from "../path/node"; import {State} from "./stateObject"; import {TargetState} from "./targetState"; import {ViewContext} from "../view/interface"; @@ -12,6 +13,14 @@ export type StateOrName = (string|StateDeclaration|State); /** * @hidden * Internal Context obj, State-view definition, transition params + * + * TODO: refactor this to only... + * + * - viewDeclarationObj + * - rawViewName + * - node + * + * ... then derive the remainder and pass to a framework specific factory function to generate the ViewConfig */ export interface StateViewConfig { /** A view block from a state config */ @@ -22,6 +31,7 @@ export interface StateViewConfig { params: any; /** The context object reference this ViewConfig belongs to */ context: ViewContext; + node: Node; } /** View declaration inside state declaration */ diff --git a/src/view/view.ts b/src/view/view.ts index e738dd611..7b0dc9d8e 100644 --- a/src/view/view.ts +++ b/src/view/view.ts @@ -1,6 +1,5 @@ "use strict"; /** @module view */ /** for typedoc */ -/// import {TemplateFactory} from "./templateFactory"; import {extend, equals, applyPairs, pick, removeFrom, TypedMap} from "../common/common"; import {curry, prop} from "../common/hof"; @@ -12,6 +11,7 @@ import {StateViewConfig, ViewDeclaration} from "../state/interface"; import {UIViewData, ViewContext} from "./interface"; import {ResolveInjector} from "../resolve/module"; +import {Node} from "../path/node"; /** * Given a raw view name from a views: config, returns a normalized target viewName and contextAnchor @@ -62,6 +62,7 @@ export class ViewConfig { params: any; locals: any; + node: Node; constructor(stateViewConfig: StateViewConfig) { // viewName is something like "$default" or "foo.bar" or "$default.foo.bar.$default" @@ -75,7 +76,7 @@ export class ViewConfig { uiViewContextAnchor = anchor.name; } - extend(this, pick(stateViewConfig, "viewDeclarationObj", "params", "context", "locals"), {uiViewName, uiViewContextAnchor}); + extend(this, pick(stateViewConfig, "viewDeclarationObj", "params", "context", "locals", "node"), {uiViewName, uiViewContextAnchor}); this.controllerAs = stateViewConfig.viewDeclarationObj.controllerAs; } diff --git a/test/viewSpec.ts b/test/viewSpec.ts index 072f0c395..70b4c32a9 100644 --- a/test/viewSpec.ts +++ b/test/viewSpec.ts @@ -74,7 +74,8 @@ describe('view', function() { rawViewName: '$default', context: { name: "blarg", parent: rootcontext }, params: {type: "Acme"}, - locals: {} + locals: {}, + node: {} }; var injector = { invokeNow: (fn, locals) => $injector.invoke(fn, null, locals), diff --git a/tsconfig-ng2.json b/tsconfig-ng2.json new file mode 100644 index 000000000..8d6afaa3e --- /dev/null +++ b/tsconfig-ng2.json @@ -0,0 +1,19 @@ +{ + "moduleResolution": "node", + "comment": "tsconfig for 'justjs' and 'ng2' builds. ng1 is built using grunt", + "compilerOptions": { + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "commonjs", + "rootDir": "src", + "sourceRoot": "src", + "target": "es5", + "outDir": "build/es5", + "declaration": true, + "sourceMap": true + }, + "files": [ + "src/ng2.ts", + "src/justjs.ts" + ] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..89270f34d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "commonjs", + "rootDir": "src", + "target": "es5", + "outDir": "build/es5", + "declaration": true, + "sourceMap": true + }, + "files": [ + "src/ng1.ts", + "src/ng1/stateEvents.ts" + ] +} diff --git a/tsd.json b/tsd.json new file mode 100644 index 000000000..cc73a3805 --- /dev/null +++ b/tsd.json @@ -0,0 +1,8 @@ +{ + "version": "v4", + "repo": "borisyankov/DefinitelyTyped", + "ref": "master", + "path": "typings", + "bundle": "typings/tsd.d.ts", + "installed": {} +} diff --git a/typings/es6-shim/es6-shim.d.ts b/typings/es6-shim/es6-shim.d.ts new file mode 100644 index 000000000..41f22997a --- /dev/null +++ b/typings/es6-shim/es6-shim.d.ts @@ -0,0 +1,668 @@ +// Type definitions for es6-shim v0.31.2 +// Project: https://github.com/paulmillr/es6-shim +// Definitions by: Ron Buckton +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +declare type PropertyKey = string | number | symbol; + +interface IteratorResult { + done: boolean; + value?: T; +} + +interface IterableShim { + /** + * Shim for an ES6 iterable. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): Iterator; +} + +interface Iterator { + next(value?: any): IteratorResult; + return?(value?: any): IteratorResult; + throw?(e?: any): IteratorResult; +} + +interface IterableIteratorShim extends IterableShim, Iterator { + /** + * Shim for an ES6 iterable iterator. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): IterableIteratorShim; +} + +interface StringConstructor { + /** + * Return the String value whose elements are, in order, the elements in the List elements. + * If length is 0, the empty string is returned. + */ + fromCodePoint(...codePoints: number[]): string; + + /** + * String.raw is intended for use as a tag function of a Tagged Template String. When called + * as such the first argument will be a well formed template call site object and the rest + * parameter will contain the substitution values. + * @param template A well-formed template string call site representation. + * @param substitutions A set of substitution values. + */ + raw(template: TemplateStringsArray, ...substitutions: any[]): string; +} + +interface String { + /** + * Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point + * value of the UTF-16 encoded code point starting at the string element at position pos in + * the String resulting from converting this object to a String. + * If there is no element at that position, the result is undefined. + * If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos. + */ + codePointAt(pos: number): number; + + /** + * Returns true if searchString appears as a substring of the result of converting this + * object to a String, at one or more positions that are + * greater than or equal to position; otherwise, returns false. + * @param searchString search string + * @param position If position is undefined, 0 is assumed, so as to search all of the String. + */ + includes(searchString: string, position?: number): boolean; + + /** + * Returns true if the sequence of elements of searchString converted to a String is the + * same as the corresponding elements of this object (converted to a String) starting at + * endPosition – length(this). Otherwise returns false. + */ + endsWith(searchString: string, endPosition?: number): boolean; + + /** + * Returns a String value that is made from count copies appended together. If count is 0, + * T is the empty String is returned. + * @param count number of copies to append + */ + repeat(count: number): string; + + /** + * Returns true if the sequence of elements of searchString converted to a String is the + * same as the corresponding elements of this object (converted to a String) starting at + * position. Otherwise returns false. + */ + startsWith(searchString: string, position?: number): boolean; + + /** + * Returns an HTML anchor element and sets the name attribute to the text value + * @param name + */ + anchor(name: string): string; + + /** Returns a HTML element */ + big(): string; + + /** Returns a HTML element */ + blink(): string; + + /** Returns a HTML element */ + bold(): string; + + /** Returns a HTML element */ + fixed(): string + + /** Returns a HTML element and sets the color attribute value */ + fontcolor(color: string): string + + /** Returns a HTML element and sets the size attribute value */ + fontsize(size: number): string; + + /** Returns a HTML element and sets the size attribute value */ + fontsize(size: string): string; + + /** Returns an HTML element */ + italics(): string; + + /** Returns an HTML element and sets the href attribute value */ + link(url: string): string; + + /** Returns a HTML element */ + small(): string; + + /** Returns a HTML element */ + strike(): string; + + /** Returns a HTML element */ + sub(): string; + + /** Returns a HTML element */ + sup(): string; + + /** + * Shim for an ES6 iterable. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): IterableIteratorShim; +} + +interface ArrayConstructor { + /** + * Creates an array from an array-like object. + * @param arrayLike An array-like object to convert to an array. + * @param mapfn A mapping function to call on every element of the array. + * @param thisArg Value of 'this' used to invoke the mapfn. + */ + from(arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): Array; + + /** + * Creates an array from an iterable object. + * @param iterable An iterable object to convert to an array. + * @param mapfn A mapping function to call on every element of the array. + * @param thisArg Value of 'this' used to invoke the mapfn. + */ + from(iterable: IterableShim, mapfn: (v: T, k: number) => U, thisArg?: any): Array; + + /** + * Creates an array from an array-like object. + * @param arrayLike An array-like object to convert to an array. + */ + from(arrayLike: ArrayLike): Array; + + /** + * Creates an array from an iterable object. + * @param iterable An iterable object to convert to an array. + */ + from(iterable: IterableShim): Array; + + /** + * Returns a new array from a set of elements. + * @param items A set of elements to include in the new array object. + */ + of(...items: T[]): Array; +} + +interface Array { + /** + * Returns the value of the first element in the array where predicate is true, and undefined + * otherwise. + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find + * immediately returns that element value. Otherwise, find returns undefined. + * @param thisArg If provided, it will be used as the this value for each invocation of + * predicate. If it is not provided, undefined is used instead. + */ + find(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): T; + + /** + * Returns the index of the first element in the array where predicate is true, and undefined + * otherwise. + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find + * immediately returns that element value. Otherwise, find returns undefined. + * @param thisArg If provided, it will be used as the this value for each invocation of + * predicate. If it is not provided, undefined is used instead. + */ + findIndex(predicate: (value: T) => boolean, thisArg?: any): number; + + /** + * Returns the this object after filling the section identified by start and end with value + * @param value value to fill array section with + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as + * length+end. + */ + fill(value: T, start?: number, end?: number): T[]; + + /** + * Returns the this object after copying a section of the array identified by start and end + * to the same array starting at position target + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it + * is treated as length+end. + * @param end If not specified, length of the this object is used as its default value. + */ + copyWithin(target: number, start: number, end?: number): T[]; + + /** + * Returns an array of key, value pairs for every entry in the array + */ + entries(): IterableIteratorShim<[number, T]>; + + /** + * Returns an list of keys in the array + */ + keys(): IterableIteratorShim; + + /** + * Returns an list of values in the array + */ + values(): IterableIteratorShim; + + /** + * Shim for an ES6 iterable. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): IterableIteratorShim; +} + +interface NumberConstructor { + /** + * The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1 + * that is representable as a Number value, which is approximately: + * 2.2204460492503130808472633361816 x 10‍−‍16. + */ + EPSILON: number; + + /** + * Returns true if passed value is finite. + * Unlike the global isFininte, Number.isFinite doesn't forcibly convert the parameter to a + * number. Only finite values of the type number, result in true. + * @param number A numeric value. + */ + isFinite(number: number): boolean; + + /** + * Returns true if the value passed is an integer, false otherwise. + * @param number A numeric value. + */ + isInteger(number: number): boolean; + + /** + * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a + * number). Unlike the global isNaN(), Number.isNaN() doesn't forcefully convert the parameter + * to a number. Only values of the type number, that are also NaN, result in true. + * @param number A numeric value. + */ + isNaN(number: number): boolean; + + /** + * Returns true if the value passed is a safe integer. + * @param number A numeric value. + */ + isSafeInteger(number: number): boolean; + + /** + * The value of the largest integer n such that n and n + 1 are both exactly representable as + * a Number value. + * The value of Number.MIN_SAFE_INTEGER is 9007199254740991 2^53 − 1. + */ + MAX_SAFE_INTEGER: number; + + /** + * The value of the smallest integer n such that n and n − 1 are both exactly representable as + * a Number value. + * The value of Number.MIN_SAFE_INTEGER is −9007199254740991 (−(2^53 − 1)). + */ + MIN_SAFE_INTEGER: number; + + /** + * Converts a string to a floating-point number. + * @param string A string that contains a floating-point number. + */ + parseFloat(string: string): number; + + /** + * Converts A string to an integer. + * @param s A string to convert into a number. + * @param radix A value between 2 and 36 that specifies the base of the number in numString. + * If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. + * All other strings are considered decimal. + */ + parseInt(string: string, radix?: number): number; +} + +interface ObjectConstructor { + /** + * Copy the values of all of the enumerable own properties from one or more source objects to a + * target object. Returns the target object. + * @param target The target object to copy to. + * @param sources One or more source objects to copy properties from. + */ + assign(target: any, ...sources: any[]): any; + + /** + * Returns true if the values are the same value, false otherwise. + * @param value1 The first value. + * @param value2 The second value. + */ + is(value1: any, value2: any): boolean; + + /** + * Sets the prototype of a specified object o to object proto or null. Returns the object o. + * @param o The object to change its prototype. + * @param proto The value of the new prototype or null. + * @remarks Requires `__proto__` support. + */ + setPrototypeOf(o: any, proto: any): any; +} + +interface RegExp { + /** + * Returns a string indicating the flags of the regular expression in question. This field is read-only. + * The characters in this string are sequenced and concatenated in the following order: + * + * - "g" for global + * - "i" for ignoreCase + * - "m" for multiline + * - "u" for unicode + * - "y" for sticky + * + * If no flags are set, the value is the empty string. + */ + flags: string; +} + +interface Math { + /** + * Returns the number of leading zero bits in the 32-bit binary representation of a number. + * @param x A numeric expression. + */ + clz32(x: number): number; + + /** + * Returns the result of 32-bit multiplication of two numbers. + * @param x First number + * @param y Second number + */ + imul(x: number, y: number): number; + + /** + * Returns the sign of the x, indicating whether x is positive, negative or zero. + * @param x The numeric expression to test + */ + sign(x: number): number; + + /** + * Returns the base 10 logarithm of a number. + * @param x A numeric expression. + */ + log10(x: number): number; + + /** + * Returns the base 2 logarithm of a number. + * @param x A numeric expression. + */ + log2(x: number): number; + + /** + * Returns the natural logarithm of 1 + x. + * @param x A numeric expression. + */ + log1p(x: number): number; + + /** + * Returns the result of (e^x - 1) of x (e raised to the power of x, where e is the base of + * the natural logarithms). + * @param x A numeric expression. + */ + expm1(x: number): number; + + /** + * Returns the hyperbolic cosine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + cosh(x: number): number; + + /** + * Returns the hyperbolic sine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + sinh(x: number): number; + + /** + * Returns the hyperbolic tangent of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + tanh(x: number): number; + + /** + * Returns the inverse hyperbolic cosine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + acosh(x: number): number; + + /** + * Returns the inverse hyperbolic sine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + asinh(x: number): number; + + /** + * Returns the inverse hyperbolic tangent of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + atanh(x: number): number; + + /** + * Returns the square root of the sum of squares of its arguments. + * @param values Values to compute the square root for. + * If no arguments are passed, the result is +0. + * If there is only one argument, the result is the absolute value. + * If any argument is +Infinity or -Infinity, the result is +Infinity. + * If any argument is NaN, the result is NaN. + * If all arguments are either +0 or −0, the result is +0. + */ + hypot(...values: number[]): number; + + /** + * Returns the integral part of the a numeric expression, x, removing any fractional digits. + * If x is already an integer, the result is x. + * @param x A numeric expression. + */ + trunc(x: number): number; + + /** + * Returns the nearest single precision float representation of a number. + * @param x A numeric expression. + */ + fround(x: number): number; + + /** + * Returns an implementation-dependent approximation to the cube root of number. + * @param x A numeric expression. + */ + cbrt(x: number): number; +} + +interface PromiseLike { + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): PromiseLike; + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): PromiseLike; +} + +/** + * Represents the completion of an asynchronous operation + */ +interface Promise { + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; + + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: (reason: any) => T | PromiseLike): Promise; + catch(onrejected?: (reason: any) => void): Promise; +} + +interface PromiseConstructor { + /** + * A reference to the prototype. + */ + prototype: Promise; + + /** + * Creates a new Promise. + * @param executor A callback used to initialize the promise. This callback is passed two arguments: + * a resolve callback used resolve the promise with a value or the result of another promise, + * and a reject callback used to reject the promise with a provided reason or error. + */ + new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; + + /** + * Creates a Promise that is resolved with an array of results when all of the provided Promises + * resolve, or rejected when any Promise is rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + all(values: IterableShim>): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: IterableShim>): Promise; + + /** + * Creates a new rejected promise for the provided reason. + * @param reason The reason the promise was rejected. + * @returns A new rejected Promise. + */ + reject(reason: any): Promise; + + /** + * Creates a new rejected promise for the provided reason. + * @param reason The reason the promise was rejected. + * @returns A new rejected Promise. + */ + reject(reason: any): Promise; + + /** + * Creates a new resolved promise for the provided value. + * @param value A promise. + * @returns A promise whose internal state matches the provided promise. + */ + resolve(value: T | PromiseLike): Promise; + + /** + * Creates a new resolved promise . + * @returns A resolved promise. + */ + resolve(): Promise; +} + +declare var Promise: PromiseConstructor; + +interface Map { + clear(): void; + delete(key: K): boolean; + forEach(callbackfn: (value: V, index: K, map: Map) => void, thisArg?: any): void; + get(key: K): V; + has(key: K): boolean; + set(key: K, value?: V): Map; + size: number; + entries(): IterableIteratorShim<[K, V]>; + keys(): IterableIteratorShim; + values(): IterableIteratorShim; +} + +interface MapConstructor { + new (): Map; + new (iterable: IterableShim<[K, V]>): Map; + prototype: Map; +} + +declare var Map: MapConstructor; + +interface Set { + add(value: T): Set; + clear(): void; + delete(value: T): boolean; + forEach(callbackfn: (value: T, index: T, set: Set) => void, thisArg?: any): void; + has(value: T): boolean; + size: number; + entries(): IterableIteratorShim<[T, T]>; + keys(): IterableIteratorShim; + values(): IterableIteratorShim; +} + +interface SetConstructor { + new (): Set; + new (iterable: IterableShim): Set; + prototype: Set; +} + +declare var Set: SetConstructor; + +interface WeakMap { + delete(key: K): boolean; + get(key: K): V; + has(key: K): boolean; + set(key: K, value?: V): WeakMap; +} + +interface WeakMapConstructor { + new (): WeakMap; + new (iterable: IterableShim<[K, V]>): WeakMap; + prototype: WeakMap; +} + +declare var WeakMap: WeakMapConstructor; + +interface WeakSet { + add(value: T): WeakSet; + delete(value: T): boolean; + has(value: T): boolean; +} + +interface WeakSetConstructor { + new (): WeakSet; + new (iterable: IterableShim): WeakSet; + prototype: WeakSet; +} + +declare var WeakSet: WeakSetConstructor; + +declare module Reflect { + function apply(target: Function, thisArgument: any, argumentsList: ArrayLike): any; + function construct(target: Function, argumentsList: ArrayLike): any; + function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean; + function deleteProperty(target: any, propertyKey: PropertyKey): boolean; + function enumerate(target: any): IterableIteratorShim; + function get(target: any, propertyKey: PropertyKey, receiver?: any): any; + function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; + function getPrototypeOf(target: any): any; + function has(target: any, propertyKey: PropertyKey): boolean; + function isExtensible(target: any): boolean; + function ownKeys(target: any): Array; + function preventExtensions(target: any): boolean; + function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean; + function setPrototypeOf(target: any, proto: any): boolean; +} + +declare module "es6-shim" { + var String: StringConstructor; + var Array: ArrayConstructor; + var Number: NumberConstructor; + var Math: Math; + var Object: ObjectConstructor; + var Map: MapConstructor; + var Set: SetConstructor; + var WeakMap: WeakMapConstructor; + var WeakSet: WeakSetConstructor; + var Promise: PromiseConstructor; + module Reflect { + function apply(target: Function, thisArgument: any, argumentsList: ArrayLike): any; + function construct(target: Function, argumentsList: ArrayLike): any; + function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean; + function deleteProperty(target: any, propertyKey: PropertyKey): boolean; + function enumerate(target: any): Iterator; + function get(target: any, propertyKey: PropertyKey, receiver?: any): any; + function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; + function getPrototypeOf(target: any): any; + function has(target: any, propertyKey: PropertyKey): boolean; + function isExtensible(target: any): boolean; + function ownKeys(target: any): Array; + function preventExtensions(target: any): boolean; + function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean; + function setPrototypeOf(target: any, proto: any): boolean; + } +}