| //------------------------------------------------------------------------------------------------------- | |
| // Copyright (C) Microsoft. All rights reserved. | |
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. | |
| //------------------------------------------------------------------------------------------------------- | |
| /// <reference path="ms-appx://Microsoft.WinJS.1.0/js/base.js" /> | |
| (function baseInit(global, undefined) { | |
| "use strict"; | |
| function initializeProperties(target, members) { | |
| var keys = Object.keys(members); | |
| var properties; | |
| var i, len; | |
| for (i = 0, len = keys.length; i < len; i++) { | |
| var key = keys[i]; | |
| var enumerable = key.charCodeAt(0) !== /*_*/95; | |
| var member = members[key]; | |
| if (member && typeof member === 'object') { | |
| if (member.value !== undefined || typeof member.get === 'function' || typeof member.set === 'function') { | |
| if (member.enumerable === undefined) { | |
| member.enumerable = enumerable; | |
| } | |
| properties = properties || {}; | |
| properties[key] = member; | |
| continue; | |
| } | |
| } | |
| if (!enumerable) { | |
| properties = properties || {}; | |
| properties[key] = { value: member, enumerable: enumerable, configurable: true, writable: true } | |
| continue; | |
| } | |
| target[key] = member; | |
| } | |
| if (properties) { | |
| Object.defineProperties(target, properties); | |
| } | |
| } | |
| (function (rootNamespace) { | |
| // Create the rootNamespace in the global namespace | |
| if (!global[rootNamespace]) { | |
| global[rootNamespace] = Object.create(Object.prototype); | |
| } | |
| // Cache the rootNamespace we just created in a local variable | |
| var _rootNamespace = global[rootNamespace]; | |
| if (!_rootNamespace.Namespace) { | |
| _rootNamespace.Namespace = Object.create(Object.prototype); | |
| } | |
| function defineWithParent(parentNamespace, name, members) { | |
| /// <signature helpKeyword="WinJS.Namespace.defineWithParent"> | |
| /// <summary locid="WinJS.Namespace.defineWithParent"> | |
| /// Defines a new namespace with the specified name under the specified parent namespace. | |
| /// </summary> | |
| /// <param name="parentNamespace" type="Object" locid="WinJS.Namespace.defineWithParent_p:parentNamespace"> | |
| /// The parent namespace. | |
| /// </param> | |
| /// <param name="name" type="String" locid="WinJS.Namespace.defineWithParent_p:name"> | |
| /// The name of the new namespace. | |
| /// </param> | |
| /// <param name="members" type="Object" locid="WinJS.Namespace.defineWithParent_p:members"> | |
| /// The members of the new namespace. | |
| /// </param> | |
| /// <returns type="Object" locid="WinJS.Namespace.defineWithParent_returnValue"> | |
| /// The newly-defined namespace. | |
| /// </returns> | |
| /// </signature> | |
| var currentNamespace = parentNamespace, | |
| namespaceFragments = name.split("."); | |
| for (var i = 0, len = namespaceFragments.length; i < len; i++) { | |
| var namespaceName = namespaceFragments[i]; | |
| if (!currentNamespace[namespaceName]) { | |
| Object.defineProperty(currentNamespace, namespaceName, | |
| { value: {}, writable: false, enumerable: true, configurable: true } | |
| ); | |
| } | |
| currentNamespace = currentNamespace[namespaceName]; | |
| } | |
| if (members) { | |
| initializeProperties(currentNamespace, members); | |
| } | |
| return currentNamespace; | |
| } | |
| function define(name, members) { | |
| /// <signature helpKeyword="WinJS.Namespace.define"> | |
| /// <summary locid="WinJS.Namespace.define"> | |
| /// Defines a new namespace with the specified name. | |
| /// </summary> | |
| /// <param name="name" type="String" locid="WinJS.Namespace.define_p:name"> | |
| /// The name of the namespace. This could be a dot-separated name for nested namespaces. | |
| /// </param> | |
| /// <param name="members" type="Object" locid="WinJS.Namespace.define_p:members"> | |
| /// The members of the new namespace. | |
| /// </param> | |
| /// <returns type="Object" locid="WinJS.Namespace.define_returnValue"> | |
| /// The newly-defined namespace. | |
| /// </returns> | |
| /// </signature> | |
| return defineWithParent(global, name, members); | |
| } | |
| // Establish members of the "WinJS.Namespace" namespace | |
| Object.defineProperties(_rootNamespace.Namespace, { | |
| defineWithParent: { value: defineWithParent, writable: true, enumerable: true, configurable: true }, | |
| define: { value: define, writable: true, enumerable: true, configurable: true } | |
| }); | |
| })("WinJS"); | |
| (function (WinJS) { | |
| function define(constructor, instanceMembers, staticMembers) { | |
| /// <signature helpKeyword="WinJS.Class.define"> | |
| /// <summary locid="WinJS.Class.define"> | |
| /// Defines a class using the given constructor and the specified instance members. | |
| /// </summary> | |
| /// <param name="constructor" type="Function" locid="WinJS.Class.define_p:constructor"> | |
| /// A constructor function that is used to instantiate this class. | |
| /// </param> | |
| /// <param name="instanceMembers" type="Object" locid="WinJS.Class.define_p:instanceMembers"> | |
| /// The set of instance fields, properties, and methods made available on the class. | |
| /// </param> | |
| /// <param name="staticMembers" type="Object" locid="WinJS.Class.define_p:staticMembers"> | |
| /// The set of static fields, properties, and methods made available on the class. | |
| /// </param> | |
| /// <returns type="Function" locid="WinJS.Class.define_returnValue"> | |
| /// The newly-defined class. | |
| /// </returns> | |
| /// </signature> | |
| constructor = constructor || function () { }; | |
| WinJS.Utilities.markSupportedForProcessing(constructor); | |
| if (instanceMembers) { | |
| initializeProperties(constructor.prototype, instanceMembers); | |
| } | |
| if (staticMembers) { | |
| initializeProperties(constructor, staticMembers); | |
| } | |
| return constructor; | |
| } | |
| function derive(baseClass, constructor, instanceMembers, staticMembers) { | |
| /// <signature helpKeyword="WinJS.Class.derive"> | |
| /// <summary locid="WinJS.Class.derive"> | |
| /// Creates a sub-class based on the supplied baseClass parameter, using prototypal inheritance. | |
| /// </summary> | |
| /// <param name="baseClass" type="Function" locid="WinJS.Class.derive_p:baseClass"> | |
| /// The class to inherit from. | |
| /// </param> | |
| /// <param name="constructor" type="Function" locid="WinJS.Class.derive_p:constructor"> | |
| /// A constructor function that is used to instantiate this class. | |
| /// </param> | |
| /// <param name="instanceMembers" type="Object" locid="WinJS.Class.derive_p:instanceMembers"> | |
| /// The set of instance fields, properties, and methods to be made available on the class. | |
| /// </param> | |
| /// <param name="staticMembers" type="Object" locid="WinJS.Class.derive_p:staticMembers"> | |
| /// The set of static fields, properties, and methods to be made available on the class. | |
| /// </param> | |
| /// <returns type="Function" locid="WinJS.Class.derive_returnValue"> | |
| /// The newly-defined class. | |
| /// </returns> | |
| /// </signature> | |
| if (baseClass) { | |
| constructor = constructor || function () { }; | |
| var basePrototype = baseClass.prototype; | |
| constructor.prototype = Object.create(basePrototype); | |
| WinJS.Utilities.markSupportedForProcessing(constructor); | |
| Object.defineProperty(constructor.prototype, "constructor", { value: constructor, writable: true, configurable: true, enumerable: true }); | |
| if (instanceMembers) { | |
| initializeProperties(constructor.prototype, instanceMembers); | |
| } | |
| if (staticMembers) { | |
| initializeProperties(constructor, staticMembers); | |
| } | |
| return constructor; | |
| } else { | |
| return define(constructor, instanceMembers, staticMembers); | |
| } | |
| } | |
| function mix(constructor) { | |
| /// <signature helpKeyword="WinJS.Class.mix"> | |
| /// <summary locid="WinJS.Class.mix"> | |
| /// Defines a class using the given constructor and the union of the set of instance members | |
| /// specified by all the mixin objects. The mixin parameter list is of variable length. | |
| /// </summary> | |
| /// <param name="constructor" locid="WinJS.Class.mix_p:constructor"> | |
| /// A constructor function that is used to instantiate this class. | |
| /// </param> | |
| /// <returns type="Function" locid="WinJS.Class.mix_returnValue"> | |
| /// The newly-defined class. | |
| /// </returns> | |
| /// </signature> | |
| constructor = constructor || function () { }; | |
| var i, len; | |
| for (i = 1, len = arguments.length; i < len; i++) { | |
| initializeProperties(constructor.prototype, arguments[i]); | |
| } | |
| return constructor; | |
| } | |
| // Establish members of "WinJS.Class" namespace | |
| WinJS.Namespace.define("WinJS.Class", { | |
| define: define, | |
| derive: derive, | |
| mix: mix | |
| }); | |
| })(WinJS); | |
| })(this); | |
| (function baseUtilsInit(global, WinJS) { | |
| "use strict"; | |
| var hasWinRT = !!global.Windows; | |
| var strings = { | |
| get notSupportedForProcessing() { return WinJS.Resources._getWinJSString("base/notSupportedForProcessing").value; } | |
| }; | |
| function nop(v) { | |
| return v; | |
| } | |
| function getMemberFiltered(name, root, filter) { | |
| return name.split(".").reduce(function (currentNamespace, name) { | |
| if (currentNamespace) { | |
| return filter(currentNamespace[name]); | |
| } | |
| return null; | |
| }, root); | |
| } | |
| // Establish members of "WinJS.Utilities" namespace | |
| WinJS.Namespace.define("WinJS.Utilities", { | |
| // Used for mocking in tests | |
| _setHasWinRT: { | |
| value: function (value) { | |
| hasWinRT = value; | |
| }, | |
| configurable: false, | |
| writable: false, | |
| enumerable: false | |
| }, | |
| /// <field type="Boolean" locid="WinJS.Utilities.hasWinRT" helpKeyword="WinJS.Utilities.hasWinRT">Determine if WinRT is accessible in this script context.</field> | |
| hasWinRT: { | |
| get: function () { return hasWinRT; }, | |
| configurable: false, | |
| enumerable: true | |
| }, | |
| _getMemberFiltered: getMemberFiltered, | |
| getMember: function (name, root) { | |
| /// <signature helpKeyword="WinJS.Utilities.getMember"> | |
| /// <summary locid="WinJS.Utilities.getMember"> | |
| /// Gets the leaf-level type or namespace specified by the name parameter. | |
| /// </summary> | |
| /// <param name="name" locid="WinJS.Utilities.getMember_p:name"> | |
| /// The name of the member. | |
| /// </param> | |
| /// <param name="root" locid="WinJS.Utilities.getMember_p:root"> | |
| /// The root to start in. Defaults to the global object. | |
| /// </param> | |
| /// <returns type="Object" locid="WinJS.Utilities.getMember_returnValue"> | |
| /// The leaf-level type or namespace in the specified parent namespace. | |
| /// </returns> | |
| /// </signature> | |
| if (!name) { | |
| return null; | |
| } | |
| return getMemberFiltered(name, root || global, nop); | |
| }, | |
| ready: function (callback, async) { | |
| /// <signature helpKeyword="WinJS.Utilities.ready"> | |
| /// <summary locid="WinJS.Utilities.ready"> | |
| /// Ensures that the specified function executes only after the DOMContentLoaded event has fired | |
| /// for the current page. | |
| /// </summary> | |
| /// <returns type="WinJS.Promise" locid="WinJS.Utilities.ready_returnValue">A promise that completes after DOMContentLoaded has occurred.</returns> | |
| /// <param name="callback" optional="true" locid="WinJS.Utilities.ready_p:callback"> | |
| /// A function that executes after DOMContentLoaded has occurred. | |
| /// </param> | |
| /// <param name="async" optional="true" locid="WinJS.Utilities.ready_p:async"> | |
| /// If true, the callback should be executed asynchronously. | |
| /// </param> | |
| /// </signature> | |
| return new WinJS.Promise(function (c, e) { | |
| function complete() { | |
| if (callback) { | |
| try { | |
| callback(); | |
| c(); | |
| } | |
| catch (err) { | |
| e(err); | |
| } | |
| } | |
| else { | |
| c(); | |
| } | |
| } | |
| var readyState = WinJS.Utilities.testReadyState; | |
| if (!readyState) { | |
| if (global.document) { | |
| readyState = document.readyState; | |
| } | |
| else { | |
| readyState = "complete"; | |
| } | |
| } | |
| if (readyState === "complete" || (global.document && document.body !== null)) { | |
| if (async) { | |
| msSetImmediate(complete); | |
| } | |
| else { | |
| complete(); | |
| } | |
| } | |
| else { | |
| global.addEventListener("DOMContentLoaded", complete, false); | |
| } | |
| }); | |
| }, | |
| /// <field type="Boolean" locid="WinJS.Utilities.strictProcessing" helpKeyword="WinJS.Utilities.strictProcessing">Determines if strict declarative processing is enabled in this script context.</field> | |
| strictProcessing: { | |
| get: function () { return true; }, | |
| configurable: false, | |
| enumerable: true, | |
| }, | |
| markSupportedForProcessing: { | |
| value: function (func) { | |
| /// <signature helpKeyword="WinJS.Utilities.markSupportedForProcessing"> | |
| /// <summary locid="WinJS.Utilities.markSupportedForProcessing"> | |
| /// Marks a function as being compatible with declarative processing, such as WinJS.UI.processAll | |
| /// or WinJS.Binding.processAll. | |
| /// </summary> | |
| /// <param name="func" type="Function" locid="WinJS.Utilities.markSupportedForProcessing_p:func"> | |
| /// The function to be marked as compatible with declarative processing. | |
| /// </param> | |
| /// <returns type="Function" locid="WinJS.Utilities.markSupportedForProcessing_returnValue"> | |
| /// The input function. | |
| /// </returns> | |
| /// </signature> | |
| func.supportedForProcessing = true; | |
| return func; | |
| }, | |
| configurable: false, | |
| writable: false, | |
| enumerable: true | |
| }, | |
| requireSupportedForProcessing: { | |
| value: function (value) { | |
| /// <signature helpKeyword="WinJS.Utilities.requireSupportedForProcessing"> | |
| /// <summary locid="WinJS.Utilities.requireSupportedForProcessing"> | |
| /// Asserts that the value is compatible with declarative processing, such as WinJS.UI.processAll | |
| /// or WinJS.Binding.processAll. If it is not compatible an exception will be thrown. | |
| /// </summary> | |
| /// <param name="value" type="Object" locid="WinJS.Utilities.requireSupportedForProcessing_p:value"> | |
| /// The value to be tested for compatibility with declarative processing. If the | |
| /// value is a function it must be marked with a property 'supportedForProcessing' | |
| /// with a value of true. | |
| /// </param> | |
| /// <returns type="Object" locid="WinJS.Utilities.requireSupportedForProcessing_returnValue"> | |
| /// The input value. | |
| /// </returns> | |
| /// </signature> | |
| var supportedForProcessing = true; | |
| supportedForProcessing = supportedForProcessing && !(value === global); | |
| supportedForProcessing = supportedForProcessing && !(value === global.location); | |
| supportedForProcessing = supportedForProcessing && !(value instanceof HTMLIFrameElement); | |
| supportedForProcessing = supportedForProcessing && !(typeof value === "function" && !value.supportedForProcessing); | |
| switch (global.frames.length) { | |
| case 0: | |
| break; | |
| case 1: | |
| supportedForProcessing = supportedForProcessing && !(value === global.frames[0]); | |
| break; | |
| default: | |
| for (var i = 0, len = global.frames.length; supportedForProcessing && i < len; i++) { | |
| supportedForProcessing = supportedForProcessing && !(value === global.frames[i]); | |
| } | |
| break; | |
| } | |
| if (supportedForProcessing) { | |
| return value; | |
| } | |
| throw new WinJS.ErrorFromName("WinJS.Utilities.requireSupportedForProcessing", WinJS.Resources._formatString(strings.notSupportedForProcessing, value)); | |
| }, | |
| configurable: false, | |
| writable: false, | |
| enumerable: true | |
| }, | |
| }); | |
| WinJS.Namespace.define("WinJS", { | |
| validation: false, | |
| strictProcessing: { | |
| value: function () { | |
| /// <signature helpKeyword="WinJS.strictProcessing"> | |
| /// <summary locid="WinJS.strictProcessing"> | |
| /// Strict processing is always enforced, this method has no effect. | |
| /// </summary> | |
| /// </signature> | |
| }, | |
| configurable: false, | |
| writable: false, | |
| enumerable: false | |
| }, | |
| }); | |
| })(this, WinJS); | |
| (function eventsInit(WinJS, undefined) { | |
| "use strict"; | |
| function createEventProperty(name) { | |
| var eventPropStateName = "_on" + name + "state"; | |
| return { | |
| get: function () { | |
| var state = this[eventPropStateName]; | |
| return state && state.userHandler; | |
| }, | |
| set: function (handler) { | |
| var state = this[eventPropStateName]; | |
| if (handler) { | |
| if (!state) { | |
| state = { wrapper: function (evt) { return state.userHandler(evt); }, userHandler: handler }; | |
| Object.defineProperty(this, eventPropStateName, { value: state, enumerable: false, writable:true, configurable: true }); | |
| this.addEventListener(name, state.wrapper, false); | |
| } | |
| state.userHandler = handler; | |
| } else if (state) { | |
| this.removeEventListener(name, state.wrapper, false); | |
| this[eventPropStateName] = null; | |
| } | |
| }, | |
| enumerable: true | |
| } | |
| } | |
| function createEventProperties(events) { | |
| /// <signature helpKeyword="WinJS.Utilities.createEventProperties"> | |
| /// <summary locid="WinJS.Utilities.createEventProperties"> | |
| /// Creates an object that has one property for each name passed to the function. | |
| /// </summary> | |
| /// <param name="events" locid="WinJS.Utilities.createEventProperties_p:events"> | |
| /// A variable list of property names. | |
| /// </param> | |
| /// <returns type="Object" locid="WinJS.Utilities.createEventProperties_returnValue"> | |
| /// The object with the specified properties. The names of the properties are prefixed with 'on'. | |
| /// </returns> | |
| /// </signature> | |
| var props = {}; | |
| for (var i = 0, len = arguments.length; i < len; i++) { | |
| var name = arguments[i]; | |
| props["on" + name] = createEventProperty(name); | |
| } | |
| return props; | |
| } | |
| var EventMixinEvent = WinJS.Class.define( | |
| function EventMixinEvent_ctor(type, detail, target) { | |
| this.detail = detail; | |
| this.target = target; | |
| this.timeStamp = Date.now(); | |
| this.type = type; | |
| }, | |
| { | |
| bubbles: { value: false, writable: false }, | |
| cancelable: { value: false, writable: false }, | |
| currentTarget: { | |
| get: function () { return this.target; } | |
| }, | |
| defaultPrevented: { | |
| get: function () { return this._preventDefaultCalled; } | |
| }, | |
| trusted: { value: false, writable: false }, | |
| eventPhase: { value: 0, writable: false }, | |
| target: null, | |
| timeStamp: null, | |
| type: null, | |
| preventDefault: function () { | |
| this._preventDefaultCalled = true; | |
| }, | |
| stopImmediatePropagation: function () { | |
| this._stopImmediatePropagationCalled = true; | |
| }, | |
| stopPropagation: function () { | |
| } | |
| }, { | |
| supportedForProcessing: false, | |
| } | |
| ); | |
| var eventMixin = { | |
| _listeners: null, | |
| addEventListener: function (type, listener, useCapture) { | |
| /// <signature helpKeyword="WinJS.Utilities.eventMixin.addEventListener"> | |
| /// <summary locid="WinJS.Utilities.eventMixin.addEventListener"> | |
| /// Adds an event listener to the control. | |
| /// </summary> | |
| /// <param name="type" locid="WinJS.Utilities.eventMixin.addEventListener_p:type"> | |
| /// The type (name) of the event. | |
| /// </param> | |
| /// <param name="listener" locid="WinJS.Utilities.eventMixin.addEventListener_p:listener"> | |
| /// The listener to invoke when the event gets raised. | |
| /// </param> | |
| /// <param name="useCapture" locid="WinJS.Utilities.eventMixin.addEventListener_p:useCapture"> | |
| /// if true initiates capture, otherwise false. | |
| /// </param> | |
| /// </signature> | |
| useCapture = useCapture || false; | |
| this._listeners = this._listeners || {}; | |
| var eventListeners = (this._listeners[type] = this._listeners[type] || []); | |
| for (var i = 0, len = eventListeners.length; i < len; i++) { | |
| var l = eventListeners[i]; | |
| if (l.useCapture === useCapture && l.listener === listener) { | |
| return; | |
| } | |
| } | |
| eventListeners.push({ listener: listener, useCapture: useCapture }); | |
| }, | |
| dispatchEvent: function (type, details) { | |
| /// <signature helpKeyword="WinJS.Utilities.eventMixin.dispatchEvent"> | |
| /// <summary locid="WinJS.Utilities.eventMixin.dispatchEvent"> | |
| /// Raises an event of the specified type and with the specified additional properties. | |
| /// </summary> | |
| /// <param name="type" locid="WinJS.Utilities.eventMixin.dispatchEvent_p:type"> | |
| /// The type (name) of the event. | |
| /// </param> | |
| /// <param name="details" locid="WinJS.Utilities.eventMixin.dispatchEvent_p:details"> | |
| /// The set of additional properties to be attached to the event object when the event is raised. | |
| /// </param> | |
| /// <returns type="Boolean" locid="WinJS.Utilities.eventMixin.dispatchEvent_returnValue"> | |
| /// true if preventDefault was called on the event. | |
| /// </returns> | |
| /// </signature> | |
| var listeners = this._listeners && this._listeners[type]; | |
| if (listeners) { | |
| var eventValue = new EventMixinEvent(type, details, this); | |
| // Need to copy the array to protect against people unregistering while we are dispatching | |
| listeners = listeners.slice(0, listeners.length); | |
| for (var i = 0, len = listeners.length; i < len && !eventValue._stopImmediatePropagationCalled; i++) { | |
| listeners[i].listener(eventValue); | |
| } | |
| return eventValue.defaultPrevented || false; | |
| } | |
| return false; | |
| }, | |
| removeEventListener: function (type, listener, useCapture) { | |
| /// <signature helpKeyword="WinJS.Utilities.eventMixin.removeEventListener"> | |
| /// <summary locid="WinJS.Utilities.eventMixin.removeEventListener"> | |
| /// Removes an event listener from the control. | |
| /// </summary> | |
| /// <param name="type" locid="WinJS.Utilities.eventMixin.removeEventListener_p:type"> | |
| /// The type (name) of the event. | |
| /// </param> | |
| /// <param name="listener" locid="WinJS.Utilities.eventMixin.removeEventListener_p:listener"> | |
| /// The listener to remove. | |
| /// </param> | |
| /// <param name="useCapture" locid="WinJS.Utilities.eventMixin.removeEventListener_p:useCapture"> | |
| /// Specifies whether to initiate capture. | |
| /// </param> | |
| /// </signature> | |
| useCapture = useCapture || false; | |
| var listeners = this._listeners && this._listeners[type]; | |
| if (listeners) { | |
| for (var i = 0, len = listeners.length; i < len; i++) { | |
| var l = listeners[i]; | |
| if (l.listener === listener && l.useCapture === useCapture) { | |
| listeners.splice(i, 1); | |
| if (listeners.length === 0) { | |
| delete this._listeners[type]; | |
| } | |
| // Only want to remove one element for each call to removeEventListener | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| }; | |
| WinJS.Namespace.define("WinJS.Utilities", { | |
| _createEventProperty: createEventProperty, | |
| createEventProperties: createEventProperties, | |
| eventMixin: eventMixin | |
| }); | |
| })(WinJS); | |
| (function promiseInit(global, undefined) { | |
| "use strict"; | |
| global.Debug && (global.Debug.setNonUserCodeExceptions = true); | |
| var ListenerType = WinJS.Class.mix(WinJS.Class.define(null, { /*empty*/ }, { supportedForProcessing: false }), WinJS.Utilities.eventMixin); | |
| var promiseEventListeners = new ListenerType(); | |
| // make sure there is a listeners collection so that we can do a more trivial check below | |
| promiseEventListeners._listeners = {}; | |
| var errorET = "error"; | |
| var canceledName = "Canceled"; | |
| var tagWithStack = false; | |
| var tag = { | |
| promise: 0x01, | |
| thenPromise: 0x02, | |
| errorPromise: 0x04, | |
| exceptionPromise: 0x08, | |
| completePromise: 0x10, | |
| }; | |
| tag.all = tag.promise | tag.thenPromise | tag.errorPromise | tag.exceptionPromise | tag.completePromise; | |
| // | |
| // Global error counter, for each error which enters the system we increment this once and then | |
| // the error number travels with the error as it traverses the tree of potential handlers. | |
| // | |
| // When someone has registered to be told about errors (WinJS.Promise.callonerror) promises | |
| // which are in error will get tagged with a ._errorId field. This tagged field is the | |
| // contract by which nested promises with errors will be identified as chaining for the | |
| // purposes of the callonerror semantics. If a nested promise in error is encountered without | |
| // a ._errorId it will be assumed to be foreign and treated as an interop boundary and | |
| // a new error id will be minted. | |
| // | |
| var error_number = 1; | |
| // | |
| // The state machine has a interesting hiccup in it with regards to notification, in order | |
| // to flatten out notification and avoid recursion for synchronous completion we have an | |
| // explicit set of *_notify states which are responsible for notifying their entire tree | |
| // of children. They can do this because they know that immediate children are always | |
| // ThenPromise instances and we can therefore reach into their state to access the | |
| // _listeners collection. | |
| // | |
| // So, what happens is that a Promise will be fulfilled through the _completed or _error | |
| // messages at which point it will enter a *_notify state and be responsible for to move | |
| // its children into an (as appropriate) success or error state and also notify that child's | |
| // listeners of the state transition, until leaf notes are reached. | |
| // | |
| var state_created, // -> working | |
| state_working, // -> error | error_notify | success | success_notify | canceled | waiting | |
| state_waiting, // -> error | error_notify | success | success_notify | waiting_canceled | |
| state_waiting_canceled, // -> error | error_notify | success | success_notify | canceling | |
| state_canceled, // -> error | error_notify | success | success_notify | canceling | |
| state_canceling, // -> error_notify | |
| state_success_notify, // -> success | |
| state_success, // -> . | |
| state_error_notify, // -> error | |
| state_error; // -> . | |
| // Noop function, used in the various states to indicate that they don't support a given | |
| // message. Named with the somewhat cute name '_' because it reads really well in the states. | |
| function _() { undefined; } | |
| // Initial state | |
| // | |
| state_created = { | |
| name: "created", | |
| enter: function (promise) { | |
| promise._setState(state_working); | |
| }, | |
| cancel: _, | |
| done: _, | |
| then: _, | |
| _completed: _, | |
| _error: _, | |
| _notify: _, | |
| _progress: _, | |
| _setCompleteValue: _, | |
| _setErrorValue: _ | |
| }; | |
| // Ready state, waiting for a message (completed/error/progress), able to be canceled | |
| // | |
| state_working = { | |
| name: "working", | |
| enter: _, | |
| cancel: function (promise) { | |
| promise._setState(state_canceled); | |
| }, | |
| done: done, | |
| then: then, | |
| _completed: completed, | |
| _error: error, | |
| _notify: _, | |
| _progress: progress, | |
| _setCompleteValue: setCompleteValue, | |
| _setErrorValue: setErrorValue | |
| }; | |
| // Waiting state, if a promise is completed with a value which is itself a promise | |
| // (has a then() method) it signs up to be informed when that child promise is | |
| // fulfilled at which point it will be fulfilled with that value. | |
| // | |
| state_waiting = { | |
| name: "waiting", | |
| enter: function (promise) { | |
| var waitedUpon = promise._value; | |
| var error = function (value) { | |
| if (waitedUpon._errorId) { | |
| promise._chainedError(value, waitedUpon); | |
| } else { | |
| // Because this is an interop boundary we want to indicate that this | |
| // error has been handled by the promise infrastructure before we | |
| // begin a new handling chain. | |
| // | |
| callonerror(promise, value, detailsForHandledError, waitedUpon, error); | |
| promise._error(value); | |
| } | |
| }; | |
| error.handlesOnError = true; | |
| waitedUpon.then( | |
| promise._completed.bind(promise), | |
| error, | |
| promise._progress.bind(promise) | |
| ); | |
| }, | |
| cancel: function (promise) { | |
| promise._setState(state_waiting_canceled); | |
| }, | |
| done: done, | |
| then: then, | |
| _completed: completed, | |
| _error: error, | |
| _notify: _, | |
| _progress: progress, | |
| _setCompleteValue: setCompleteValue, | |
| _setErrorValue: setErrorValue | |
| }; | |
| // Waiting canceled state, when a promise has been in a waiting state and receives a | |
| // request to cancel its pending work it will forward that request to the child promise | |
| // and then waits to be informed of the result. This promise moves itself into the | |
| // canceling state but understands that the child promise may instead push it to a | |
| // different state. | |
| // | |
| state_waiting_canceled = { | |
| name: "waiting_canceled", | |
| enter: function (promise) { | |
| // Initiate a transition to canceling. Triggering a cancel on the promise | |
| // that we are waiting upon may result in a different state transition | |
| // before the state machine pump runs again. | |
| promise._setState(state_canceling); | |
| var waitedUpon = promise._value; | |
| if (waitedUpon.cancel) { | |
| waitedUpon.cancel(); | |
| } | |
| }, | |
| cancel: _, | |
| done: done, | |
| then: then, | |
| _completed: completed, | |
| _error: error, | |
| _notify: _, | |
| _progress: progress, | |
| _setCompleteValue: setCompleteValue, | |
| _setErrorValue: setErrorValue | |
| }; | |
| // Canceled state, moves to the canceling state and then tells the promise to do | |
| // whatever it might need to do on cancelation. | |
| // | |
| state_canceled = { | |
| name: "canceled", | |
| enter: function (promise) { | |
| // Initiate a transition to canceling. The _cancelAction may change the state | |
| // before the state machine pump runs again. | |
| promise._setState(state_canceling); | |
| promise._cancelAction(); | |
| }, | |
| cancel: _, | |
| done: done, | |
| then: then, | |
| _completed: completed, | |
| _error: error, | |
| _notify: _, | |
| _progress: progress, | |
| _setCompleteValue: setCompleteValue, | |
| _setErrorValue: setErrorValue | |
| }; | |
| // Canceling state, commits to the promise moving to an error state with an error | |
| // object whose 'name' and 'message' properties contain the string "Canceled" | |
| // | |
| state_canceling = { | |
| name: "canceling", | |
| enter: function (promise) { | |
| var error = new Error(canceledName); | |
| error.name = error.message; | |
| promise._value = error; | |
| promise._setState(state_error_notify); | |
| }, | |
| cancel: _, | |
| done: _, | |
| then: _, | |
| _completed: _, | |
| _error: _, | |
| _notify: _, | |
| _progress: _, | |
| _setCompleteValue: _, | |
| _setErrorValue: _ | |
| }; | |
| // Success notify state, moves a promise to the success state and notifies all children | |
| // | |
| state_success_notify = { | |
| name: "complete_notify", | |
| enter: function (promise) { | |
| promise.done = CompletePromise.prototype.done; | |
| promise.then = CompletePromise.prototype.then; | |
| if (promise._listeners) { | |
| var queue = [promise]; | |
| var p; | |
| while (queue.length) { | |
| p = queue.pop(); | |
| p._state._notify(p, queue); | |
| } | |
| } | |
| promise._setState(state_success); | |
| }, | |
| cancel: _, | |
| done: null, /*error to get here */ | |
| then: null, /*error to get here */ | |
| _completed: _, | |
| _error: _, | |
| _notify: notifySuccess, | |
| _progress: _, | |
| _setCompleteValue: _, | |
| _setErrorValue: _ | |
| }; | |
| // Success state, moves a promise to the success state and does NOT notify any children. | |
| // Some upstream promise is owning the notification pass. | |
| // | |
| state_success = { | |
| name: "success", | |
| enter: function (promise) { | |
| promise.done = CompletePromise.prototype.done; | |
| promise.then = CompletePromise.prototype.then; | |
| promise._cleanupAction(); | |
| }, | |
| cancel: _, | |
| done: null, /*error to get here */ | |
| then: null, /*error to get here */ | |
| _completed: _, | |
| _error: _, | |
| _notify: notifySuccess, | |
| _progress: _, | |
| _setCompleteValue: _, | |
| _setErrorValue: _ | |
| }; | |
| // Error notify state, moves a promise to the error state and notifies all children | |
| // | |
| state_error_notify = { | |
| name: "error_notify", | |
| enter: function (promise) { | |
| promise.done = ErrorPromise.prototype.done; | |
| promise.then = ErrorPromise.prototype.then; | |
| if (promise._listeners) { | |
| var queue = [promise]; | |
| var p; | |
| while (queue.length) { | |
| p = queue.pop(); | |
| p._state._notify(p, queue); | |
| } | |
| } | |
| promise._setState(state_error); | |
| }, | |
| cancel: _, | |
| done: null, /*error to get here*/ | |
| then: null, /*error to get here*/ | |
| _completed: _, | |
| _error: _, | |
| _notify: notifyError, | |
| _progress: _, | |
| _setCompleteValue: _, | |
| _setErrorValue: _ | |
| }; | |
| // Error state, moves a promise to the error state and does NOT notify any children. | |
| // Some upstream promise is owning the notification pass. | |
| // | |
| state_error = { | |
| name: "error", | |
| enter: function (promise) { | |
| promise.done = ErrorPromise.prototype.done; | |
| promise.then = ErrorPromise.prototype.then; | |
| promise._cleanupAction(); | |
| }, | |
| cancel: _, | |
| done: null, /*error to get here*/ | |
| then: null, /*error to get here*/ | |
| _completed: _, | |
| _error: _, | |
| _notify: notifyError, | |
| _progress: _, | |
| _setCompleteValue: _, | |
| _setErrorValue: _ | |
| }; | |
| // | |
| // The statemachine implementation follows a very particular pattern, the states are specified | |
| // as static stateless bags of functions which are then indirected through the state machine | |
| // instance (a Promise). As such all of the functions on each state have the promise instance | |
| // passed to them explicitly as a parameter and the Promise instance members do a little | |
| // dance where they indirect through the state and insert themselves in the argument list. | |
| // | |
| // We could instead call directly through the promise states however then every caller | |
| // would have to remember to do things like pumping the state machine to catch state transitions. | |
| // | |
| var PromiseStateMachine = WinJS.Class.define(null, { | |
| _listeners: null, | |
| _nextState: null, | |
| _state: null, | |
| _value: null, | |
| cancel: function () { | |
| /// <signature helpKeyword="WinJS.PromiseStateMachine.cancel"> | |
| /// <summary locid="WinJS.PromiseStateMachine.cancel"> | |
| /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't | |
| /// already been fulfilled and cancellation is supported, the promise enters | |
| /// the error state with a value of Error("Canceled"). | |
| /// </summary> | |
| /// </signature> | |
| this._state.cancel(this); | |
| this._run(); | |
| }, | |
| done: function Promise_done(onComplete, onError, onProgress) { | |
| /// <signature helpKeyword="WinJS.PromiseStateMachine.done"> | |
| /// <summary locid="WinJS.PromiseStateMachine.done"> | |
| /// Allows you to specify the work to be done on the fulfillment of the promised value, | |
| /// the error handling to be performed if the promise fails to fulfill | |
| /// a value, and the handling of progress notifications along the way. | |
| /// | |
| /// After the handlers have finished executing, this function throws any error that would have been returned | |
| /// from then() as a promise in the error state. | |
| /// </summary> | |
| /// <param name="onComplete" type="Function" locid="WinJS.PromiseStateMachine.done_p:onComplete"> | |
| /// The function to be called if the promise is fulfilled successfully with a value. | |
| /// The fulfilled value is passed as the single argument. If the value is null, | |
| /// the fulfilled value is returned. The value returned | |
| /// from the function becomes the fulfilled value of the promise returned by | |
| /// then(). If an exception is thrown while executing the function, the promise returned | |
| /// by then() moves into the error state. | |
| /// </param> | |
| /// <param name="onError" type="Function" optional="true" locid="WinJS.PromiseStateMachine.done_p:onError"> | |
| /// The function to be called if the promise is fulfilled with an error. The error | |
| /// is passed as the single argument. If it is null, the error is forwarded. | |
| /// The value returned from the function is the fulfilled value of the promise returned by then(). | |
| /// </param> | |
| /// <param name="onProgress" type="Function" optional="true" locid="WinJS.PromiseStateMachine.done_p:onProgress"> | |
| /// the function to be called if the promise reports progress. Data about the progress | |
| /// is passed as the single argument. Promises are not required to support | |
| /// progress. | |
| /// </param> | |
| /// </signature> | |
| this._state.done(this, onComplete, onError, onProgress); | |
| }, | |
| then: function Promise_then(onComplete, onError, onProgress) { | |
| /// <signature helpKeyword="WinJS.PromiseStateMachine.then"> | |
| /// <summary locid="WinJS.PromiseStateMachine.then"> | |
| /// Allows you to specify the work to be done on the fulfillment of the promised value, | |
| /// the error handling to be performed if the promise fails to fulfill | |
| /// a value, and the handling of progress notifications along the way. | |
| /// </summary> | |
| /// <param name="onComplete" type="Function" locid="WinJS.PromiseStateMachine.then_p:onComplete"> | |
| /// The function to be called if the promise is fulfilled successfully with a value. | |
| /// The value is passed as the single argument. If the value is null, the value is returned. | |
| /// The value returned from the function becomes the fulfilled value of the promise returned by | |
| /// then(). If an exception is thrown while this function is being executed, the promise returned | |
| /// by then() moves into the error state. | |
| /// </param> | |
| /// <param name="onError" type="Function" optional="true" locid="WinJS.PromiseStateMachine.then_p:onError"> | |
| /// The function to be called if the promise is fulfilled with an error. The error | |
| /// is passed as the single argument. If it is null, the error is forwarded. | |
| /// The value returned from the function becomes the fulfilled value of the promise returned by then(). | |
| /// </param> | |
| /// <param name="onProgress" type="Function" optional="true" locid="WinJS.PromiseStateMachine.then_p:onProgress"> | |
| /// The function to be called if the promise reports progress. Data about the progress | |
| /// is passed as the single argument. Promises are not required to support | |
| /// progress. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.PromiseStateMachine.then_returnValue"> | |
| /// The promise whose value is the result of executing the complete or | |
| /// error function. | |
| /// </returns> | |
| /// </signature> | |
| return this._state.then(this, onComplete, onError, onProgress); | |
| }, | |
| _chainedError: function (value, context) { | |
| var result = this._state._error(this, value, detailsForChainedError, context); | |
| this._run(); | |
| return result; | |
| }, | |
| _completed: function (value) { | |
| var result = this._state._completed(this, value); | |
| this._run(); | |
| return result; | |
| }, | |
| _error: function (value) { | |
| var result = this._state._error(this, value, detailsForError); | |
| this._run(); | |
| return result; | |
| }, | |
| _progress: function (value) { | |
| this._state._progress(this, value); | |
| }, | |
| _setState: function (state) { | |
| this._nextState = state; | |
| }, | |
| _setCompleteValue: function (value) { | |
| this._state._setCompleteValue(this, value); | |
| this._run(); | |
| }, | |
| _setChainedErrorValue: function (value, context) { | |
| var result = this._state._setErrorValue(this, value, detailsForChainedError, context); | |
| this._run(); | |
| return result; | |
| }, | |
| _setExceptionValue: function (value) { | |
| var result = this._state._setErrorValue(this, value, detailsForException); | |
| this._run(); | |
| return result; | |
| }, | |
| _run: function () { | |
| while (this._nextState) { | |
| this._state = this._nextState; | |
| this._nextState = null; | |
| this._state.enter(this); | |
| } | |
| } | |
| }, { | |
| supportedForProcessing: false | |
| }); | |
| // | |
| // Implementations of shared state machine code. | |
| // | |
| function completed(promise, value) { | |
| var targetState; | |
| if (value && typeof value === "object" && typeof value.then === "function") { | |
| targetState = state_waiting; | |
| } else { | |
| targetState = state_success_notify; | |
| } | |
| promise._value = value; | |
| promise._setState(targetState); | |
| } | |
| function createErrorDetails(exception, error, promise, id, parent, handler) { | |
| return { | |
| exception: exception, | |
| error: error, | |
| promise: promise, | |
| handler: handler, | |
| id: id, | |
| parent: parent | |
| }; | |
| } | |
| function detailsForHandledError(promise, errorValue, context, handler) { | |
| var exception = context._isException; | |
| var errorId = context._errorId; | |
| return createErrorDetails( | |
| exception ? errorValue : null, | |
| exception ? null : errorValue, | |
| promise, | |
| errorId, | |
| context, | |
| handler | |
| ); | |
| } | |
| function detailsForChainedError(promise, errorValue, context) { | |
| var exception = context._isException; | |
| var errorId = context._errorId; | |
| setErrorInfo(promise, errorId, exception); | |
| return createErrorDetails( | |
| exception ? errorValue : null, | |
| exception ? null : errorValue, | |
| promise, | |
| errorId, | |
| context | |
| ); | |
| } | |
| function detailsForError(promise, errorValue) { | |
| var errorId = ++error_number; | |
| setErrorInfo(promise, errorId); | |
| return createErrorDetails( | |
| null, | |
| errorValue, | |
| promise, | |
| errorId | |
| ); | |
| } | |
| function detailsForException(promise, exceptionValue) { | |
| var errorId = ++error_number; | |
| setErrorInfo(promise, errorId, true); | |
| return createErrorDetails( | |
| exceptionValue, | |
| null, | |
| promise, | |
| errorId | |
| ); | |
| } | |
| function done(promise, onComplete, onError, onProgress) { | |
| pushListener(promise, { c: onComplete, e: onError, p: onProgress }); | |
| } | |
| function error(promise, value, onerrorDetails, context) { | |
| promise._value = value; | |
| callonerror(promise, value, onerrorDetails, context); | |
| promise._setState(state_error_notify); | |
| } | |
| function notifySuccess(promise, queue) { | |
| var value = promise._value; | |
| var listeners = promise._listeners; | |
| if (!listeners) { | |
| return; | |
| } | |
| promise._listeners = null; | |
| var i, len; | |
| for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { | |
| var listener = len === 1 ? listeners : listeners[i]; | |
| var onComplete = listener.c; | |
| var target = listener.promise; | |
| if (target) { | |
| try { | |
| target._setCompleteValue(onComplete ? onComplete(value) : value); | |
| } catch (ex) { | |
| target._setExceptionValue(ex); | |
| } | |
| if (target._state !== state_waiting && target._listeners) { | |
| queue.push(target); | |
| } | |
| } else { | |
| CompletePromise.prototype.done.call(promise, onComplete); | |
| } | |
| } | |
| } | |
| function notifyError(promise, queue) { | |
| var value = promise._value; | |
| var listeners = promise._listeners; | |
| if (!listeners) { | |
| return; | |
| } | |
| promise._listeners = null; | |
| var i, len; | |
| for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { | |
| var listener = len === 1 ? listeners : listeners[i]; | |
| var onError = listener.e; | |
| var target = listener.promise; | |
| if (target) { | |
| try { | |
| if (onError) { | |
| if (!onError.handlesOnError) { | |
| callonerror(target, value, detailsForHandledError, promise, onError); | |
| } | |
| target._setCompleteValue(onError(value)) | |
| } else { | |
| target._setChainedErrorValue(value, promise); | |
| } | |
| } catch (ex) { | |
| target._setExceptionValue(ex); | |
| } | |
| if (target._state !== state_waiting && target._listeners) { | |
| queue.push(target); | |
| } | |
| } else { | |
| ErrorPromise.prototype.done.call(promise, null, onError); | |
| } | |
| } | |
| } | |
| function callonerror(promise, value, onerrorDetailsGenerator, context, handler) { | |
| if (promiseEventListeners._listeners[errorET]) { | |
| if (value instanceof Error && value.message === canceledName) { | |
| return; | |
| } | |
| promiseEventListeners.dispatchEvent(errorET, onerrorDetailsGenerator(promise, value, context, handler)); | |
| } | |
| } | |
| function progress(promise, value) { | |
| var listeners = promise._listeners; | |
| if (listeners) { | |
| var i, len; | |
| for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { | |
| var listener = len === 1 ? listeners : listeners[i]; | |
| var onProgress = listener.p; | |
| if (onProgress) { | |
| try { onProgress(value); } catch (ex) { } | |
| } | |
| if (!(listener.c || listener.e) && listener.promise) { | |
| listener.promise._progress(value); | |
| } | |
| } | |
| } | |
| } | |
| function pushListener(promise, listener) { | |
| var listeners = promise._listeners; | |
| if (listeners) { | |
| // We may have either a single listener (which will never be wrapped in an array) | |
| // or 2+ listeners (which will be wrapped). Since we are now adding one more listener | |
| // we may have to wrap the single listener before adding the second. | |
| listeners = Array.isArray(listeners) ? listeners : [listeners]; | |
| listeners.push(listener); | |
| } else { | |
| listeners = listener; | |
| } | |
| promise._listeners = listeners; | |
| } | |
| // The difference beween setCompleteValue()/setErrorValue() and complete()/error() is that setXXXValue() moves | |
| // a promise directly to the success/error state without starting another notification pass (because one | |
| // is already ongoing). | |
| function setErrorInfo(promise, errorId, isException) { | |
| promise._isException = isException || false; | |
| promise._errorId = errorId; | |
| } | |
| function setErrorValue(promise, value, onerrorDetails, context) { | |
| promise._value = value; | |
| callonerror(promise, value, onerrorDetails, context); | |
| promise._setState(state_error); | |
| } | |
| function setCompleteValue(promise, value) { | |
| var targetState; | |
| if (value && typeof value === "object" && typeof value.then === "function") { | |
| targetState = state_waiting; | |
| } else { | |
| targetState = state_success; | |
| } | |
| promise._value = value; | |
| promise._setState(targetState); | |
| } | |
| function then(promise, onComplete, onError, onProgress) { | |
| var result = new ThenPromise(promise); | |
| pushListener(promise, { promise: result, c: onComplete, e: onError, p: onProgress }); | |
| return result; | |
| } | |
| // | |
| // Internal implementation detail promise, ThenPromise is created when a promise needs | |
| // to be returned from a then() method. | |
| // | |
| var ThenPromise = WinJS.Class.derive(PromiseStateMachine, | |
| function (creator) { | |
| if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.thenPromise))) { | |
| this._stack = WinJS.Promise._getStack(); | |
| } | |
| this._creator = creator; | |
| this._setState(state_created); | |
| this._run(); | |
| }, { | |
| _creator: null, | |
| _cancelAction: function () { if (this._creator) { this._creator.cancel(); } }, | |
| _cleanupAction: function () { this._creator = null; } | |
| }, { | |
| supportedForProcessing: false | |
| } | |
| ); | |
| // | |
| // Slim promise implementations for already completed promises, these are created | |
| // under the hood on synchronous completion paths as well as by WinJS.Promise.wrap | |
| // and WinJS.Promise.wrapError. | |
| // | |
| var ErrorPromise = WinJS.Class.define( | |
| function ErrorPromise_ctor(value) { | |
| if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.errorPromise))) { | |
| this._stack = WinJS.Promise._getStack(); | |
| } | |
| this._value = value; | |
| callonerror(this, value, detailsForError); | |
| }, { | |
| cancel: function () { | |
| /// <signature helpKeyword="WinJS.PromiseStateMachine.cancel"> | |
| /// <summary locid="WinJS.PromiseStateMachine.cancel"> | |
| /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't | |
| /// already been fulfilled and cancellation is supported, the promise enters | |
| /// the error state with a value of Error("Canceled"). | |
| /// </summary> | |
| /// </signature> | |
| }, | |
| done: function ErrorPromise_done(unused, onError) { | |
| /// <signature helpKeyword="WinJS.PromiseStateMachine.done"> | |
| /// <summary locid="WinJS.PromiseStateMachine.done"> | |
| /// Allows you to specify the work to be done on the fulfillment of the promised value, | |
| /// the error handling to be performed if the promise fails to fulfill | |
| /// a value, and the handling of progress notifications along the way. | |
| /// | |
| /// After the handlers have finished executing, this function throws any error that would have been returned | |
| /// from then() as a promise in the error state. | |
| /// </summary> | |
| /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.done_p:onComplete"> | |
| /// The function to be called if the promise is fulfilled successfully with a value. | |
| /// The fulfilled value is passed as the single argument. If the value is null, | |
| /// the fulfilled value is returned. The value returned | |
| /// from the function becomes the fulfilled value of the promise returned by | |
| /// then(). If an exception is thrown while executing the function, the promise returned | |
| /// by then() moves into the error state. | |
| /// </param> | |
| /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onError"> | |
| /// The function to be called if the promise is fulfilled with an error. The error | |
| /// is passed as the single argument. If it is null, the error is forwarded. | |
| /// The value returned from the function is the fulfilled value of the promise returned by then(). | |
| /// </param> | |
| /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onProgress"> | |
| /// the function to be called if the promise reports progress. Data about the progress | |
| /// is passed as the single argument. Promises are not required to support | |
| /// progress. | |
| /// </param> | |
| /// </signature> | |
| var value = this._value; | |
| if (onError) { | |
| try { | |
| if (!onError.handlesOnError) { | |
| callonerror(null, value, detailsForHandledError, this, onError); | |
| } | |
| var result = onError(value); | |
| if (result && typeof result === "object" && typeof result.done === "function") { | |
| // If a promise is returned we need to wait on it. | |
| result.done(); | |
| } | |
| return; | |
| } catch (ex) { | |
| value = ex; | |
| } | |
| } | |
| if (value instanceof Error && value.message === canceledName) { | |
| // suppress cancel | |
| return; | |
| } | |
| // force the exception to be thrown asyncronously to avoid any try/catch blocks | |
| // | |
| setImmediate(function () { | |
| throw value; | |
| }); | |
| }, | |
| then: function ErrorPromise_then(unused, onError) { | |
| /// <signature helpKeyword="WinJS.PromiseStateMachine.then"> | |
| /// <summary locid="WinJS.PromiseStateMachine.then"> | |
| /// Allows you to specify the work to be done on the fulfillment of the promised value, | |
| /// the error handling to be performed if the promise fails to fulfill | |
| /// a value, and the handling of progress notifications along the way. | |
| /// </summary> | |
| /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.then_p:onComplete"> | |
| /// The function to be called if the promise is fulfilled successfully with a value. | |
| /// The value is passed as the single argument. If the value is null, the value is returned. | |
| /// The value returned from the function becomes the fulfilled value of the promise returned by | |
| /// then(). If an exception is thrown while this function is being executed, the promise returned | |
| /// by then() moves into the error state. | |
| /// </param> | |
| /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onError"> | |
| /// The function to be called if the promise is fulfilled with an error. The error | |
| /// is passed as the single argument. If it is null, the error is forwarded. | |
| /// The value returned from the function becomes the fulfilled value of the promise returned by then(). | |
| /// </param> | |
| /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onProgress"> | |
| /// The function to be called if the promise reports progress. Data about the progress | |
| /// is passed as the single argument. Promises are not required to support | |
| /// progress. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.PromiseStateMachine.then_returnValue"> | |
| /// The promise whose value is the result of executing the complete or | |
| /// error function. | |
| /// </returns> | |
| /// </signature> | |
| // If the promise is already in a error state and no error handler is provided | |
| // we optimize by simply returning the promise instead of creating a new one. | |
| // | |
| if (!onError) { return this; } | |
| var result; | |
| var value = this._value; | |
| try { | |
| if (!onError.handlesOnError) { | |
| callonerror(null, value, detailsForHandledError, this, onError); | |
| } | |
| result = new CompletePromise(onError(value)); | |
| } catch (ex) { | |
| // If the value throw from the error handler is the same as the value | |
| // provided to the error handler then there is no need for a new promise. | |
| // | |
| if (ex === value) { | |
| result = this; | |
| } else { | |
| result = new ExceptionPromise(ex); | |
| } | |
| } | |
| return result; | |
| } | |
| }, { | |
| supportedForProcessing: false | |
| } | |
| ); | |
| var ExceptionPromise = WinJS.Class.derive(ErrorPromise, | |
| function ExceptionPromise_ctor(value) { | |
| if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.exceptionPromise))) { | |
| this._stack = WinJS.Promise._getStack(); | |
| } | |
| this._value = value; | |
| callonerror(this, value, detailsForException); | |
| }, { | |
| /* empty */ | |
| }, { | |
| supportedForProcessing: false | |
| } | |
| ); | |
| var CompletePromise = WinJS.Class.define( | |
| function CompletePromise_ctor(value) { | |
| if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.completePromise))) { | |
| this._stack = WinJS.Promise._getStack(); | |
| } | |
| if (value && typeof value === "object" && typeof value.then === "function") { | |
| var result = new ThenPromise(null); | |
| result._setCompleteValue(value); | |
| return result; | |
| } | |
| this._value = value; | |
| }, { | |
| cancel: function () { | |
| /// <signature helpKeyword="WinJS.PromiseStateMachine.cancel"> | |
| /// <summary locid="WinJS.PromiseStateMachine.cancel"> | |
| /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't | |
| /// already been fulfilled and cancellation is supported, the promise enters | |
| /// the error state with a value of Error("Canceled"). | |
| /// </summary> | |
| /// </signature> | |
| }, | |
| done: function CompletePromise_done(onComplete) { | |
| /// <signature helpKeyword="WinJS.PromiseStateMachine.done"> | |
| /// <summary locid="WinJS.PromiseStateMachine.done"> | |
| /// Allows you to specify the work to be done on the fulfillment of the promised value, | |
| /// the error handling to be performed if the promise fails to fulfill | |
| /// a value, and the handling of progress notifications along the way. | |
| /// | |
| /// After the handlers have finished executing, this function throws any error that would have been returned | |
| /// from then() as a promise in the error state. | |
| /// </summary> | |
| /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.done_p:onComplete"> | |
| /// The function to be called if the promise is fulfilled successfully with a value. | |
| /// The fulfilled value is passed as the single argument. If the value is null, | |
| /// the fulfilled value is returned. The value returned | |
| /// from the function becomes the fulfilled value of the promise returned by | |
| /// then(). If an exception is thrown while executing the function, the promise returned | |
| /// by then() moves into the error state. | |
| /// </param> | |
| /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onError"> | |
| /// The function to be called if the promise is fulfilled with an error. The error | |
| /// is passed as the single argument. If it is null, the error is forwarded. | |
| /// The value returned from the function is the fulfilled value of the promise returned by then(). | |
| /// </param> | |
| /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.done_p:onProgress"> | |
| /// the function to be called if the promise reports progress. Data about the progress | |
| /// is passed as the single argument. Promises are not required to support | |
| /// progress. | |
| /// </param> | |
| /// </signature> | |
| if (!onComplete) { return; } | |
| try { | |
| var result = onComplete(this._value); | |
| if (result && typeof result === "object" && typeof result.done === "function") { | |
| result.done(); | |
| } | |
| } catch (ex) { | |
| // force the exception to be thrown asynchronously to avoid any try/catch blocks | |
| setImmediate(function () { | |
| throw ex; | |
| }); | |
| } | |
| }, | |
| then: function CompletePromise_then(onComplete) { | |
| /// <signature helpKeyword="WinJS.PromiseStateMachine.then"> | |
| /// <summary locid="WinJS.PromiseStateMachine.then"> | |
| /// Allows you to specify the work to be done on the fulfillment of the promised value, | |
| /// the error handling to be performed if the promise fails to fulfill | |
| /// a value, and the handling of progress notifications along the way. | |
| /// </summary> | |
| /// <param name='onComplete' type='Function' locid="WinJS.PromiseStateMachine.then_p:onComplete"> | |
| /// The function to be called if the promise is fulfilled successfully with a value. | |
| /// The value is passed as the single argument. If the value is null, the value is returned. | |
| /// The value returned from the function becomes the fulfilled value of the promise returned by | |
| /// then(). If an exception is thrown while this function is being executed, the promise returned | |
| /// by then() moves into the error state. | |
| /// </param> | |
| /// <param name='onError' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onError"> | |
| /// The function to be called if the promise is fulfilled with an error. The error | |
| /// is passed as the single argument. If it is null, the error is forwarded. | |
| /// The value returned from the function becomes the fulfilled value of the promise returned by then(). | |
| /// </param> | |
| /// <param name='onProgress' type='Function' optional='true' locid="WinJS.PromiseStateMachine.then_p:onProgress"> | |
| /// The function to be called if the promise reports progress. Data about the progress | |
| /// is passed as the single argument. Promises are not required to support | |
| /// progress. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.PromiseStateMachine.then_returnValue"> | |
| /// The promise whose value is the result of executing the complete or | |
| /// error function. | |
| /// </returns> | |
| /// </signature> | |
| try { | |
| // If the value returned from the completion handler is the same as the value | |
| // provided to the completion handler then there is no need for a new promise. | |
| // | |
| var newValue = onComplete ? onComplete(this._value) : this._value; | |
| return newValue === this._value ? this : new CompletePromise(newValue); | |
| } catch (ex) { | |
| return new ExceptionPromise(ex); | |
| } | |
| } | |
| }, { | |
| supportedForProcessing: false | |
| } | |
| ); | |
| // | |
| // Promise is the user-creatable WinJS.Promise object. | |
| // | |
| function timeout(timeoutMS) { | |
| var id; | |
| return new WinJS.Promise( | |
| function (c) { | |
| if (timeoutMS) { | |
| id = setTimeout(c, timeoutMS); | |
| } else { | |
| setImmediate(c); | |
| } | |
| }, | |
| function () { | |
| if (id) { | |
| clearTimeout(id); | |
| } | |
| } | |
| ); | |
| } | |
| function timeoutWithPromise(timeout, promise) { | |
| var cancelPromise = function () { promise.cancel(); } | |
| var cancelTimeout = function () { timeout.cancel(); } | |
| timeout.then(cancelPromise); | |
| promise.then(cancelTimeout, cancelTimeout); | |
| return promise; | |
| } | |
| var staticCanceledPromise; | |
| var Promise = WinJS.Class.derive(PromiseStateMachine, | |
| function Promise_ctor(init, oncancel) { | |
| this._oncancel = oncancel; | |
| this._setState(state_created); | |
| this._state = null; | |
| this._run(); | |
| try { | |
| var complete = this._completed.bind(this); | |
| var error = this._error.bind(this); | |
| var progress = this._progress.bind(this); | |
| init(complete, error, progress); | |
| } catch (ex) { | |
| this._setExceptionValue(ex); | |
| } | |
| }, { | |
| _oncancel: null, | |
| _cancelAction: function () { | |
| if (this._oncancel) { | |
| try { this._oncancel(); } catch (ex) { } | |
| } | |
| }, | |
| _cleanupAction: function () { this._oncancel = null; } | |
| }, { | |
| addEventListener: function Promise_addEventListener(eventType, listener, capture) { | |
| /// <signature helpKeyword="WinJS.Promise.addEventListener"> | |
| /// <summary locid="WinJS.Promise.addEventListener"> | |
| /// Adds an event listener to the control. | |
| /// </summary> | |
| /// <param name="eventType" locid="WinJS.Promise.addEventListener_p:eventType"> | |
| /// The type (name) of the event. | |
| /// </param> | |
| /// <param name="listener" locid="WinJS.Promise.addEventListener_p:listener"> | |
| /// The listener to invoke when the event is raised. | |
| /// </param> | |
| /// <param name="capture" locid="WinJS.Promise.addEventListener_p:capture"> | |
| /// Specifies whether or not to initiate capture. | |
| /// </param> | |
| /// </signature> | |
| promiseEventListeners.addEventListener(eventType, listener, capture); | |
| }, | |
| any: function Promise_any(values) { | |
| /// <signature helpKeyword="WinJS.Promise.any"> | |
| /// <summary locid="WinJS.Promise.any"> | |
| /// Returns a promise that is fulfilled when one of the input promises | |
| /// has been fulfilled. | |
| /// </summary> | |
| /// <param name="values" type="Array" locid="WinJS.Promise.any_p:values"> | |
| /// An array that contains promise objects or objects whose property | |
| /// values include promise objects. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.Promise.any_returnValue"> | |
| /// A promise that on fulfillment yields the value of the input (complete or error). | |
| /// </returns> | |
| /// </signature> | |
| return new Promise( | |
| function (complete, error, progress) { | |
| var keys = Object.keys(values); | |
| var errors = Array.isArray(values) ? [] : {}; | |
| if (keys.length === 0) { | |
| complete(); | |
| } | |
| var canceled = 0; | |
| keys.forEach(function (key) { | |
| Promise.as(values[key]).then( | |
| function () { complete({ key: key, value: values[key] }); }, | |
| function (e) { | |
| if (e instanceof Error && e.name === canceledName) { | |
| if ((++canceled) === keys.length) { | |
| complete(WinJS.Promise.cancel); | |
| } | |
| return; | |
| } | |
| error({ key: key, value: values[key] }); | |
| } | |
| ); | |
| }); | |
| }, | |
| function () { | |
| var keys = Object.keys(values); | |
| keys.forEach(function (key) { | |
| var promise = Promise.as(values[key]); | |
| if (typeof promise.cancel === "function") { | |
| promise.cancel(); | |
| } | |
| }); | |
| } | |
| ); | |
| }, | |
| as: function Promise_as(value) { | |
| /// <signature helpKeyword="WinJS.Promise.as"> | |
| /// <summary locid="WinJS.Promise.as"> | |
| /// Returns a promise. If the object is already a promise it is returned; | |
| /// otherwise the object is wrapped in a promise. | |
| /// </summary> | |
| /// <param name="value" locid="WinJS.Promise.as_p:value"> | |
| /// The value to be treated as a promise. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.Promise.as_returnValue"> | |
| /// A promise. | |
| /// </returns> | |
| /// </signature> | |
| if (value && typeof value === "object" && typeof value.then === "function") { | |
| return value; | |
| } | |
| return new CompletePromise(value); | |
| }, | |
| /// <field type="WinJS.Promise" helpKeyword="WinJS.Promise.cancel" locid="WinJS.Promise.cancel"> | |
| /// Canceled promise value, can be returned from a promise completion handler | |
| /// to indicate cancelation of the promise chain. | |
| /// </field> | |
| cancel: { | |
| get: function () { | |
| return (staticCanceledPromise = staticCanceledPromise || new ErrorPromise(new WinJS.ErrorFromName(canceledName))); | |
| } | |
| }, | |
| dispatchEvent: function Promise_dispatchEvent(eventType, details) { | |
| /// <signature helpKeyword="WinJS.Promise.dispatchEvent"> | |
| /// <summary locid="WinJS.Promise.dispatchEvent"> | |
| /// Raises an event of the specified type and properties. | |
| /// </summary> | |
| /// <param name="eventType" locid="WinJS.Promise.dispatchEvent_p:eventType"> | |
| /// The type (name) of the event. | |
| /// </param> | |
| /// <param name="details" locid="WinJS.Promise.dispatchEvent_p:details"> | |
| /// The set of additional properties to be attached to the event object. | |
| /// </param> | |
| /// <returns type="Boolean" locid="WinJS.Promise.dispatchEvent_returnValue"> | |
| /// Specifies whether preventDefault was called on the event. | |
| /// </returns> | |
| /// </signature> | |
| return promiseEventListeners.dispatchEvent(eventType, details); | |
| }, | |
| is: function Promise_is(value) { | |
| /// <signature helpKeyword="WinJS.Promise.is"> | |
| /// <summary locid="WinJS.Promise.is"> | |
| /// Determines whether a value fulfills the promise contract. | |
| /// </summary> | |
| /// <param name="value" locid="WinJS.Promise.is_p:value"> | |
| /// A value that may be a promise. | |
| /// </param> | |
| /// <returns type="Boolean" locid="WinJS.Promise.is_returnValue"> | |
| /// true if the specified value is a promise, otherwise false. | |
| /// </returns> | |
| /// </signature> | |
| return value && typeof value === "object" && typeof value.then === "function"; | |
| }, | |
| join: function Promise_join(values) { | |
| /// <signature helpKeyword="WinJS.Promise.join"> | |
| /// <summary locid="WinJS.Promise.join"> | |
| /// Creates a promise that is fulfilled when all the values are fulfilled. | |
| /// </summary> | |
| /// <param name="values" type="Object" locid="WinJS.Promise.join_p:values"> | |
| /// An object whose fields contain values, some of which may be promises. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.Promise.join_returnValue"> | |
| /// A promise whose value is an object with the same field names as those of the object in the values parameter, where | |
| /// each field value is the fulfilled value of a promise. | |
| /// </returns> | |
| /// </signature> | |
| return new Promise( | |
| function (complete, error, progress) { | |
| var keys = Object.keys(values); | |
| var errors = Array.isArray(values) ? [] : {}; | |
| var results = Array.isArray(values) ? [] : {}; | |
| var undefineds = 0; | |
| var pending = keys.length; | |
| var argDone = function (key) { | |
| if ((--pending) === 0) { | |
| var errorCount = Object.keys(errors).length; | |
| if (errorCount === 0) { | |
| complete(results); | |
| } else { | |
| var canceledCount = 0; | |
| keys.forEach(function (key) { | |
| var e = errors[key]; | |
| if (e instanceof Error && e.name === canceledName) { | |
| canceledCount++; | |
| } | |
| }); | |
| if (canceledCount === errorCount) { | |
| complete(WinJS.Promise.cancel); | |
| } else { | |
| error(errors); | |
| } | |
| } | |
| } else { | |
| progress({ Key: key, Done: true }); | |
| } | |
| }; | |
| keys.forEach(function (key) { | |
| var value = values[key]; | |
| if (value === undefined) { | |
| undefineds++; | |
| } else { | |
| Promise.then(value, | |
| function (value) { results[key] = value; argDone(key); }, | |
| function (value) { errors[key] = value; argDone(key); } | |
| ); | |
| } | |
| }); | |
| pending -= undefineds; | |
| if (pending === 0) { | |
| complete(results); | |
| return; | |
| } | |
| }, | |
| function () { | |
| Object.keys(values).forEach(function (key) { | |
| var promise = Promise.as(values[key]); | |
| if (typeof promise.cancel === "function") { | |
| promise.cancel(); | |
| } | |
| }); | |
| } | |
| ); | |
| }, | |
| removeEventListener: function Promise_removeEventListener(eventType, listener, capture) { | |
| /// <signature helpKeyword="WinJS.Promise.removeEventListener"> | |
| /// <summary locid="WinJS.Promise.removeEventListener"> | |
| /// Removes an event listener from the control. | |
| /// </summary> | |
| /// <param name='eventType' locid="WinJS.Promise.removeEventListener_eventType"> | |
| /// The type (name) of the event. | |
| /// </param> | |
| /// <param name='listener' locid="WinJS.Promise.removeEventListener_listener"> | |
| /// The listener to remove. | |
| /// </param> | |
| /// <param name='capture' locid="WinJS.Promise.removeEventListener_capture"> | |
| /// Specifies whether or not to initiate capture. | |
| /// </param> | |
| /// </signature> | |
| promiseEventListeners.removeEventListener(eventType, listener, capture); | |
| }, | |
| supportedForProcessing: false, | |
| then: function Promise_then(value, onComplete, onError, onProgress) { | |
| /// <signature helpKeyword="WinJS.Promise.then"> | |
| /// <summary locid="WinJS.Promise.then"> | |
| /// A static version of the promise instance method then(). | |
| /// </summary> | |
| /// <param name="value" locid="WinJS.Promise.then_p:value"> | |
| /// the value to be treated as a promise. | |
| /// </param> | |
| /// <param name="onComplete" type="Function" locid="WinJS.Promise.then_p:complete"> | |
| /// The function to be called if the promise is fulfilled with a value. | |
| /// If it is null, the promise simply | |
| /// returns the value. The value is passed as the single argument. | |
| /// </param> | |
| /// <param name="onError" type="Function" optional="true" locid="WinJS.Promise.then_p:error"> | |
| /// The function to be called if the promise is fulfilled with an error. The error | |
| /// is passed as the single argument. | |
| /// </param> | |
| /// <param name="onProgress" type="Function" optional="true" locid="WinJS.Promise.then_p:progress"> | |
| /// The function to be called if the promise reports progress. Data about the progress | |
| /// is passed as the single argument. Promises are not required to support | |
| /// progress. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.Promise.then_returnValue"> | |
| /// A promise whose value is the result of executing the provided complete function. | |
| /// </returns> | |
| /// </signature> | |
| return Promise.as(value).then(onComplete, onError, onProgress); | |
| }, | |
| thenEach: function Promise_thenEach(values, onComplete, onError, onProgress) { | |
| /// <signature helpKeyword="WinJS.Promise.thenEach"> | |
| /// <summary locid="WinJS.Promise.thenEach"> | |
| /// Performs an operation on all the input promises and returns a promise | |
| /// that has the shape of the input and contains the result of the operation | |
| /// that has been performed on each input. | |
| /// </summary> | |
| /// <param name="values" locid="WinJS.Promise.thenEach_p:values"> | |
| /// A set of values (which could be either an array or an object) of which some or all are promises. | |
| /// </param> | |
| /// <param name="onComplete" type="Function" locid="WinJS.Promise.thenEach_p:complete"> | |
| /// The function to be called if the promise is fulfilled with a value. | |
| /// If the value is null, the promise returns the value. | |
| /// The value is passed as the single argument. | |
| /// </param> | |
| /// <param name="onError" type="Function" optional="true" locid="WinJS.Promise.thenEach_p:error"> | |
| /// The function to be called if the promise is fulfilled with an error. The error | |
| /// is passed as the single argument. | |
| /// </param> | |
| /// <param name="onProgress" type="Function" optional="true" locid="WinJS.Promise.thenEach_p:progress"> | |
| /// The function to be called if the promise reports progress. Data about the progress | |
| /// is passed as the single argument. Promises are not required to support | |
| /// progress. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.Promise.thenEach_returnValue"> | |
| /// A promise that is the result of calling Promise.join on the values parameter. | |
| /// </returns> | |
| /// </signature> | |
| var result = Array.isArray(values) ? [] : {}; | |
| Object.keys(values).forEach(function (key) { | |
| result[key] = Promise.as(values[key]).then(onComplete, onError, onProgress); | |
| }); | |
| return Promise.join(result); | |
| }, | |
| timeout: function Promise_timeout(time, promise) { | |
| /// <signature helpKeyword="WinJS.Promise.timeout"> | |
| /// <summary locid="WinJS.Promise.timeout"> | |
| /// Creates a promise that is fulfilled after a timeout. | |
| /// </summary> | |
| /// <param name="timeout" type="Number" optional="true" locid="WinJS.Promise.timeout_p:timeout"> | |
| /// The timeout period in milliseconds. If this value is zero or not specified | |
| /// setImmediate is called, otherwise setTimeout is called. | |
| /// </param> | |
| /// <param name="promise" type="Promise" optional="true" locid="WinJS.Promise.timeout_p:promise"> | |
| /// A promise that will be canceled if it doesn't complete before the | |
| /// timeout has expired. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.Promise.timeout_returnValue"> | |
| /// A promise that is completed asynchronously after the specified timeout. | |
| /// </returns> | |
| /// </signature> | |
| var to = timeout(time); | |
| return promise ? timeoutWithPromise(to, promise) : to; | |
| }, | |
| wrap: function Promise_wrap(value) { | |
| /// <signature helpKeyword="WinJS.Promise.wrap"> | |
| /// <summary locid="WinJS.Promise.wrap"> | |
| /// Wraps a non-promise value in a promise. You can use this function if you need | |
| /// to pass a value to a function that requires a promise. | |
| /// </summary> | |
| /// <param name="value" locid="WinJS.Promise.wrap_p:value"> | |
| /// Some non-promise value to be wrapped in a promise. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.Promise.wrap_returnValue"> | |
| /// A promise that is successfully fulfilled with the specified value | |
| /// </returns> | |
| /// </signature> | |
| return new CompletePromise(value); | |
| }, | |
| wrapError: function Promise_wrapError(error) { | |
| /// <signature helpKeyword="WinJS.Promise.wrapError"> | |
| /// <summary locid="WinJS.Promise.wrapError"> | |
| /// Wraps a non-promise error value in a promise. You can use this function if you need | |
| /// to pass an error to a function that requires a promise. | |
| /// </summary> | |
| /// <param name="error" locid="WinJS.Promise.wrapError_p:error"> | |
| /// A non-promise error value to be wrapped in a promise. | |
| /// </param> | |
| /// <returns type="WinJS.Promise" locid="WinJS.Promise.wrapError_returnValue"> | |
| /// A promise that is in an error state with the specified value. | |
| /// </returns> | |
| /// </signature> | |
| return new ErrorPromise(error); | |
| }, | |
| _veryExpensiveTagWithStack: { | |
| get: function () { return tagWithStack; }, | |
| set: function (value) { tagWithStack = value; } | |
| }, | |
| _veryExpensiveTagWithStack_tag: tag, | |
| _getStack: function () { | |
| if (Debug.debuggerEnabled) { | |
| try { throw new Error(); } catch (e) { return e.stack; } | |
| } | |
| }, | |
| } | |
| ); | |
| Object.defineProperties(Promise, WinJS.Utilities.createEventProperties(errorET)); | |
| var SignalPromise = WinJS.Class.derive(PromiseStateMachine, | |
| function (cancel) { | |
| this._oncancel = cancel; | |
| this._setState(state_created); | |
| this._run(); | |
| }, { | |
| _cancelAction: function () { this._oncancel && this._oncancel(); }, | |
| _cleanupAction: function () { this._oncancel = null; } | |
| }, { | |
| supportedForProcessing: false | |
| } | |
| ); | |
| var Signal = WinJS.Class.define( | |
| function Signal_ctor(oncancel) { | |
| this._promise = new SignalPromise(oncancel); | |
| }, { | |
| promise: { | |
| get: function () { return this._promise; } | |
| }, | |
| cancel: function Signal_cancel() { | |
| this._promise.cancel(); | |
| }, | |
| complete: function Signal_complete(value) { | |
| this._promise._completed(value); | |
| }, | |
| error: function Signal_error(value) { | |
| this._promise._error(value); | |
| }, | |
| progress: function Signal_progress(value) { | |
| this._promise._progress(value); | |
| } | |
| }, { | |
| supportedForProcessing: false, | |
| } | |
| ); | |
| // Publish WinJS.Promise | |
| // | |
| WinJS.Namespace.define("WinJS", { | |
| Promise: Promise, | |
| _Signal: Signal | |
| }); | |
| }(this)); | |
| //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF | |
| //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO | |
| //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A | |
| //// PARTICULAR PURPOSE. | |
| //// | |
| //// Copyright (c) Microsoft Corporation. All rights reserved | |
| (function () { | |
| "use strict"; | |
| var Test1 = WinJS.Class.define(null, { | |
| execute: function () { | |
| var that = this; | |
| var num1 = 1; | |
| var num2 = 2; | |
| asyncAdd(num1, num2). | |
| then(function (v) { | |
| num1 = v; | |
| num2 = 3; | |
| // this return value is passed along to the next promise chain | |
| return asyncAdd(v, num2); | |
| }) | |
| } | |
| }); | |
| // Do an add asynchronously (via setTimeout) | |
| function asyncAdd(num1, num2) { | |
| var complete; | |
| var promise = new WinJS.Promise(function (complete) { | |
| var sum = num1 + num2; | |
| // this promise is completed when the complete() function is called which also | |
| // returns the value (result) of the promise. | |
| complete(sum); | |
| }); | |
| return promise; | |
| } | |
| var test1 = new Test1(); | |
| test1.execute(); | |
| WScript.Attach( function () { | |
| test1.execute(); | |
| WScript.Echo("PASSED"); | |
| }); | |
| })(); | |