提交 8a80b8c8 编写于 作者: A Alex Dima

Simplify WinJS usage

上级 c2fd3c65
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Extracted from https://github.com/winjs/winjs
* Version: 4.4.0(ec3258a9f3a36805a187848984e3bb938044178d)
* Copyright (c) Microsoft Corporation.
* All Rights Reserved.
* Licensed under the MIT License.
*/
(function() {
var _modules = Object.create(null);//{};
_modules["WinJS/Core/_WinJS"] = {};
var _winjs = function(moduleId, deps, factory) {
var exports = {};
var exportsPassedIn = false;
var depsValues = deps.map(function(dep) {
if (dep === 'exports') {
exportsPassedIn = true;
return exports;
}
return _modules[dep];
});
var result = factory.apply({}, depsValues);
_modules[moduleId] = exportsPassedIn ? exports : result;
};
_winjs("WinJS/Core/_Global", [], function () {
"use strict";
// Appease jshint
/* global window, self, global */
var globalObject =
typeof window !== 'undefined' ? window :
typeof self !== 'undefined' ? self :
typeof global !== 'undefined' ? global :
{};
return globalObject;
});
_winjs("WinJS/Core/_BaseCoreUtils", ["WinJS/Core/_Global"], function baseCoreUtilsInit(_Global) {
"use strict";
var hasWinRT = !!_Global.Windows;
function markSupportedForProcessing(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;
}
var actualSetImmediate = null;
return {
hasWinRT: hasWinRT,
markSupportedForProcessing: markSupportedForProcessing,
_setImmediate: function (callback) {
// BEGIN monaco change
if (actualSetImmediate === null) {
if (_Global.setImmediate) {
actualSetImmediate = _Global.setImmediate.bind(_Global);
} else if (typeof process !== 'undefined' && typeof process.nextTick === 'function') {
actualSetImmediate = process.nextTick.bind(process);
} else {
actualSetImmediate = _Global.setTimeout.bind(_Global);
}
}
actualSetImmediate(callback);
// END monaco change
}
};
});
_winjs("WinJS/Core/_WriteProfilerMark", ["WinJS/Core/_Global"], function profilerInit(_Global) {
"use strict";
return _Global.msWriteProfilerMark || function () { };
});
_winjs("WinJS/Core/_Base", ["WinJS/Core/_WinJS","WinJS/Core/_Global","WinJS/Core/_BaseCoreUtils","WinJS/Core/_WriteProfilerMark"], function baseInit(_WinJS, _Global, _BaseCoreUtils, _WriteProfilerMark) {
"use strict";
function initializeProperties(target, members, prefix) {
var keys = Object.keys(members);
var isArray = Array.isArray(target);
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;
}
if (prefix && member.setName && typeof member.setName === 'function') {
member.setName(prefix + "." + key);
}
properties = properties || {};
properties[key] = member;
continue;
}
}
if (!enumerable) {
properties = properties || {};
properties[key] = { value: member, enumerable: enumerable, configurable: true, writable: true };
continue;
}
if (isArray) {
target.forEach(function (target) {
target[key] = member;
});
} else {
target[key] = member;
}
}
if (properties) {
if (isArray) {
target.forEach(function (target) {
Object.defineProperties(target, properties);
});
} else {
Object.defineProperties(target, properties);
}
}
}
(function () {
var _rootNamespace = _WinJS;
if (!_rootNamespace.Namespace) {
_rootNamespace.Namespace = Object.create(Object.prototype);
}
function createNamespace(parentNamespace, name) {
var currentNamespace = parentNamespace || {};
if (name) {
var namespaceFragments = name.split(".");
if (currentNamespace === _Global && namespaceFragments[0] === "WinJS") {
currentNamespace = _WinJS;
namespaceFragments.splice(0, 1);
}
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];
}
}
return currentNamespace;
}
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 = createNamespace(parentNamespace, name);
if (members) {
initializeProperties(currentNamespace, members, name || "<ANONYMOUS>");
}
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);
}
var LazyStates = {
uninitialized: 1,
working: 2,
initialized: 3,
};
function lazy(f) {
var name;
var state = LazyStates.uninitialized;
var result;
return {
setName: function (value) {
name = value;
},
get: function () {
switch (state) {
case LazyStates.initialized:
return result;
case LazyStates.uninitialized:
state = LazyStates.working;
try {
_WriteProfilerMark("WinJS.Namespace._lazy:" + name + ",StartTM");
result = f();
} finally {
_WriteProfilerMark("WinJS.Namespace._lazy:" + name + ",StopTM");
state = LazyStates.uninitialized;
}
f = null;
state = LazyStates.initialized;
return result;
case LazyStates.working:
throw "Illegal: reentrancy on initialization";
default:
throw "Illegal";
}
},
set: function (value) {
switch (state) {
case LazyStates.working:
throw "Illegal: reentrancy on initialization";
default:
state = LazyStates.initialized;
result = value;
break;
}
},
enumerable: true,
configurable: true,
};
}
// helper for defining AMD module members
function moduleDefine(exports, name, members) {
var target = [exports];
var publicNS = null;
if (name) {
publicNS = createNamespace(_Global, name);
target.push(publicNS);
}
initializeProperties(target, members, name || "<ANONYMOUS>");
return publicNS;
}
// 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 },
_lazy: { value: lazy, writable: true, enumerable: true, configurable: true },
_moduleDefine: { value: moduleDefine, writable: true, enumerable: true, configurable: true }
});
})();
(function () {
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 () { };
_BaseCoreUtils.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);
_BaseCoreUtils.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
});
})();
define(['./winjs.base.raw'], function (winjs) {
'use strict';
return {
Promise: winjs.Promise,
TPromise: winjs.Promise,
PPromise: winjs.Promise
Namespace: _WinJS.Namespace,
Class: _WinJS.Class
};
});
_winjs("WinJS/Core/_ErrorFromName", ["WinJS/Core/_Base"], function errorsInit(_Base) {
"use strict";
var ErrorFromName = _Base.Class.derive(Error, function (name, message) {
/// <signature helpKeyword="WinJS.ErrorFromName">
/// <summary locid="WinJS.ErrorFromName">
/// Creates an Error object with the specified name and message properties.
/// </summary>
/// <param name="name" type="String" locid="WinJS.ErrorFromName_p:name">The name of this error. The name is meant to be consumed programmatically and should not be localized.</param>
/// <param name="message" type="String" optional="true" locid="WinJS.ErrorFromName_p:message">The message for this error. The message is meant to be consumed by humans and should be localized.</param>
/// <returns type="Error" locid="WinJS.ErrorFromName_returnValue">Error instance with .name and .message properties populated</returns>
/// </signature>
this.name = name;
this.message = message || name;
}, {
/* empty */
}, {
supportedForProcessing: false,
});
_Base.Namespace.define("WinJS", {
// ErrorFromName establishes a simple pattern for returning error codes.
//
ErrorFromName: ErrorFromName
});
return ErrorFromName;
});
_winjs("WinJS/Core/_Events", ["exports","WinJS/Core/_Base"], function eventsInit(exports, _Base) {
"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() {
/// <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 = _Base.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 is 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;
}
}
}
}
};
_Base.Namespace._moduleDefine(exports, "WinJS.Utilities", {
_createEventProperty: createEventProperty,
createEventProperties: createEventProperties,
eventMixin: eventMixin
});
});
_winjs("WinJS/Core/_Trace", ["WinJS/Core/_Global"], function traceInit(_Global) {
"use strict";
function nop(v) {
return v;
}
return {
_traceAsyncOperationStarting: (_Global.Debug && _Global.Debug.msTraceAsyncOperationStarting && _Global.Debug.msTraceAsyncOperationStarting.bind(_Global.Debug)) || nop,
_traceAsyncOperationCompleted: (_Global.Debug && _Global.Debug.msTraceAsyncOperationCompleted && _Global.Debug.msTraceAsyncOperationCompleted.bind(_Global.Debug)) || nop,
_traceAsyncCallbackStarting: (_Global.Debug && _Global.Debug.msTraceAsyncCallbackStarting && _Global.Debug.msTraceAsyncCallbackStarting.bind(_Global.Debug)) || nop,
_traceAsyncCallbackCompleted: (_Global.Debug && _Global.Debug.msTraceAsyncCallbackCompleted && _Global.Debug.msTraceAsyncCallbackCompleted.bind(_Global.Debug)) || nop
};
});
_winjs("WinJS/Promise/_StateMachine", ["WinJS/Core/_Global","WinJS/Core/_BaseCoreUtils","WinJS/Core/_Base","WinJS/Core/_ErrorFromName","WinJS/Core/_Events","WinJS/Core/_Trace"], function promiseStateMachineInit(_Global, _BaseCoreUtils, _Base, _ErrorFromName, _Events, _Trace) {
"use strict";
_Global.Debug && (_Global.Debug.setNonUserCodeExceptions = true);
var ListenerType = _Base.Class.mix(_Base.Class.define(null, { /*empty*/ }, { supportedForProcessing: false }), _Events.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 _() { }
// 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;
// We can special case our own intermediate promises which are not in a
// terminal state by just pushing this promise as a listener without
// having to create new indirection functions
if (waitedUpon instanceof ThenPromise &&
waitedUpon._state !== state_error &&
waitedUpon._state !== state_success) {
pushListener(waitedUpon, { promise: promise });
} else {
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.shift();
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.shift();
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 = _Base.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) {
var asyncOpID = _Trace._traceAsyncOperationStarting("WinJS.Promise.done");
pushListener(promise, { c: onComplete, e: onError, p: onProgress, asyncOpID: asyncOpID });
}
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;
_Trace._traceAsyncOperationCompleted(listener.asyncOpID, _Global.Debug && _Global.Debug.MS_ASYNC_OP_STATUS_SUCCESS);
if (target) {
_Trace._traceAsyncCallbackStarting(listener.asyncOpID);
try {
target._setCompleteValue(onComplete ? onComplete(value) : value);
} catch (ex) {
target._setExceptionValue(ex);
} finally {
_Trace._traceAsyncCallbackCompleted();
}
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;
var errorID = _Global.Debug && (value && value.name === canceledName ? _Global.Debug.MS_ASYNC_OP_STATUS_CANCELED : _Global.Debug.MS_ASYNC_OP_STATUS_ERROR);
_Trace._traceAsyncOperationCompleted(listener.asyncOpID, errorID);
if (target) {
var asyncCallbackStarted = false;
try {
if (onError) {
_Trace._traceAsyncCallbackStarting(listener.asyncOpID);
asyncCallbackStarted = true;
if (!onError.handlesOnError) {
callonerror(target, value, detailsForHandledError, promise, onError);
}
target._setCompleteValue(onError(value));
} else {
target._setChainedErrorValue(value, promise);
}
} catch (ex) {
target._setExceptionValue(ex);
} finally {
if (asyncCallbackStarted) {
_Trace._traceAsyncCallbackCompleted();
}
}
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);
var asyncOpID = _Trace._traceAsyncOperationStarting("WinJS.Promise.then");
pushListener(promise, { promise: result, c: onComplete, e: onError, p: onProgress, asyncOpID: asyncOpID });
return result;
}
//
// Internal implementation detail promise, ThenPromise is created when a promise needs
// to be returned from a then() method.
//
var ThenPromise = _Base.Class.derive(PromiseStateMachine,
function (creator) {
if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.thenPromise))) {
this._stack = 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 = _Base.Class.define(
function ErrorPromise_ctor(value) {
if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.errorPromise))) {
this._stack = 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
//
Promise._doneHandler(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 = _Base.Class.derive(ErrorPromise,
function ExceptionPromise_ctor(value) {
if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.exceptionPromise))) {
this._stack = Promise._getStack();
}
this._value = value;
callonerror(this, value, detailsForException);
}, {
/* empty */
}, {
supportedForProcessing: false
}
);
var CompletePromise = _Base.Class.define(
function CompletePromise_ctor(value) {
if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.completePromise))) {
this._stack = 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
Promise._doneHandler(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 Promise(
function (c) {
if (timeoutMS) {
id = _Global.setTimeout(c, timeoutMS);
} else {
_BaseCoreUtils._setImmediate(c);
}
},
function () {
if (id) {
_Global.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 = _Base.Class.derive(PromiseStateMachine,
function Promise_ctor(init, oncancel) {
/// <signature helpKeyword="WinJS.Promise">
/// <summary locid="WinJS.Promise">
/// A promise provides a mechanism to schedule work to be done on a value that
/// has not yet been computed. It is a convenient abstraction for managing
/// interactions with asynchronous APIs.
/// </summary>
/// <param name="init" type="Function" locid="WinJS.Promise_p:init">
/// The function that is called during construction of the promise. The function
/// is given three arguments (complete, error, progress). Inside this function
/// you should add event listeners for the notifications supported by this value.
/// </param>
/// <param name="oncancel" optional="true" locid="WinJS.Promise_p:oncancel">
/// The function to call if a consumer of this promise wants
/// to cancel its undone work. Promises are not required to
/// support cancellation.
/// </param>
/// </signature>
if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.promise))) {
this._stack = Promise._getStack();
}
this._oncancel = oncancel;
this._setState(state_created);
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 () {
// BEGIN monaco change
try {
if (this._oncancel) {
this._oncancel();
} else {
throw new Error('Promise did not implement oncancel');
}
} catch (ex) {
// Access fields to get them created
var msg = ex.message;
var stack = ex.stack;
promiseEventListeners.dispatchEvent('error', ex);
}
// END monaco change
},
_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) {
var keys = Object.keys(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(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 _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(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 (_Global.Debug && _Global.Debug.debuggerEnabled) {
try { throw new Error(); } catch (e) { return e.stack; }
}
},
_cancelBlocker: function Promise__cancelBlocker(input, oncancel) {
//
// Returns a promise which on cancelation will still result in downstream cancelation while
// protecting the promise 'input' from being canceled which has the effect of allowing
// 'input' to be shared amoung various consumers.
//
if (!Promise.is(input)) {
return Promise.wrap(input);
}
var complete;
var error;
var output = new Promise(
function (c, e) {
complete = c;
error = e;
},
function () {
complete = null;
error = null;
oncancel && oncancel();
}
);
input.then(
function (v) { complete && complete(v); },
function (e) { error && error(e); }
);
return output;
},
}
);
Object.defineProperties(Promise, _Events.createEventProperties(errorET));
Promise._doneHandler = function (value) {
_BaseCoreUtils._setImmediate(function Promise_done_rethrow() {
throw value;
});
};
return {
PromiseStateMachine: PromiseStateMachine,
Promise: Promise,
state_created: state_created
};
});
_winjs("WinJS/Promise", ["WinJS/Core/_Base","WinJS/Promise/_StateMachine"], function promiseInit( _Base, _StateMachine) {
"use strict";
_Base.Namespace.define("WinJS", {
Promise: _StateMachine.Promise
});
return _StateMachine.Promise;
});
var exported = _modules["WinJS/Core/_WinJS"];
exported.TPromise = exported.Promise;
exported.PPromise = exported.Promise;
if (typeof exports === 'undefined' && typeof define === 'function' && define.amd) {
define([], exported);
} else {
module.exports = exported;
}
})();
\ No newline at end of file
/**
* Extracted from https://github.com/winjs/winjs
* Version: 4.4.0(ec3258a9f3a36805a187848984e3bb938044178d)
* Copyright (c) Microsoft Corporation.
* All Rights Reserved.
* Licensed under the MIT License.
*/
(function() {
var _modules = Object.create(null);//{};
_modules["WinJS/Core/_WinJS"] = {};
var _winjs = function(moduleId, deps, factory) {
var exports = {};
var exportsPassedIn = false;
var depsValues = deps.map(function(dep) {
if (dep === 'exports') {
exportsPassedIn = true;
return exports;
}
return _modules[dep];
});
var result = factory.apply({}, depsValues);
_modules[moduleId] = exportsPassedIn ? exports : result;
};
_winjs("WinJS/Core/_Global", [], function () {
"use strict";
// Appease jshint
/* global window, self, global */
var globalObject =
typeof window !== 'undefined' ? window :
typeof self !== 'undefined' ? self :
typeof global !== 'undefined' ? global :
{};
return globalObject;
});
_winjs("WinJS/Core/_BaseCoreUtils", ["WinJS/Core/_Global"], function baseCoreUtilsInit(_Global) {
"use strict";
var hasWinRT = !!_Global.Windows;
function markSupportedForProcessing(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;
}
var actualSetImmediate = null;
return {
hasWinRT: hasWinRT,
markSupportedForProcessing: markSupportedForProcessing,
_setImmediate: function (callback) {
// BEGIN monaco change
if (actualSetImmediate === null) {
if (_Global.setImmediate) {
actualSetImmediate = _Global.setImmediate.bind(_Global);
} else if (typeof process !== 'undefined' && typeof process.nextTick === 'function') {
actualSetImmediate = process.nextTick.bind(process);
} else {
actualSetImmediate = _Global.setTimeout.bind(_Global);
}
}
actualSetImmediate(callback);
// END monaco change
}
};
});
_winjs("WinJS/Core/_WriteProfilerMark", ["WinJS/Core/_Global"], function profilerInit(_Global) {
"use strict";
return _Global.msWriteProfilerMark || function () { };
});
_winjs("WinJS/Core/_Base", ["WinJS/Core/_WinJS","WinJS/Core/_Global","WinJS/Core/_BaseCoreUtils","WinJS/Core/_WriteProfilerMark"], function baseInit(_WinJS, _Global, _BaseCoreUtils, _WriteProfilerMark) {
"use strict";
function initializeProperties(target, members, prefix) {
var keys = Object.keys(members);
var isArray = Array.isArray(target);
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;
}
if (prefix && member.setName && typeof member.setName === 'function') {
member.setName(prefix + "." + key);
}
properties = properties || {};
properties[key] = member;
continue;
}
}
if (!enumerable) {
properties = properties || {};
properties[key] = { value: member, enumerable: enumerable, configurable: true, writable: true };
continue;
}
if (isArray) {
target.forEach(function (target) {
target[key] = member;
});
} else {
target[key] = member;
}
}
if (properties) {
if (isArray) {
target.forEach(function (target) {
Object.defineProperties(target, properties);
});
} else {
Object.defineProperties(target, properties);
}
}
}
(function () {
var _rootNamespace = _WinJS;
if (!_rootNamespace.Namespace) {
_rootNamespace.Namespace = Object.create(Object.prototype);
}
function createNamespace(parentNamespace, name) {
var currentNamespace = parentNamespace || {};
if (name) {
var namespaceFragments = name.split(".");
if (currentNamespace === _Global && namespaceFragments[0] === "WinJS") {
currentNamespace = _WinJS;
namespaceFragments.splice(0, 1);
}
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];
}
}
return currentNamespace;
}
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 = createNamespace(parentNamespace, name);
if (members) {
initializeProperties(currentNamespace, members, name || "<ANONYMOUS>");
}
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);
}
var LazyStates = {
uninitialized: 1,
working: 2,
initialized: 3,
};
function lazy(f) {
var name;
var state = LazyStates.uninitialized;
var result;
return {
setName: function (value) {
name = value;
},
get: function () {
switch (state) {
case LazyStates.initialized:
return result;
case LazyStates.uninitialized:
state = LazyStates.working;
try {
_WriteProfilerMark("WinJS.Namespace._lazy:" + name + ",StartTM");
result = f();
} finally {
_WriteProfilerMark("WinJS.Namespace._lazy:" + name + ",StopTM");
state = LazyStates.uninitialized;
}
f = null;
state = LazyStates.initialized;
return result;
case LazyStates.working:
throw "Illegal: reentrancy on initialization";
default:
throw "Illegal";
}
},
set: function (value) {
switch (state) {
case LazyStates.working:
throw "Illegal: reentrancy on initialization";
default:
state = LazyStates.initialized;
result = value;
break;
}
},
enumerable: true,
configurable: true,
};
}
// helper for defining AMD module members
function moduleDefine(exports, name, members) {
var target = [exports];
var publicNS = null;
if (name) {
publicNS = createNamespace(_Global, name);
target.push(publicNS);
}
initializeProperties(target, members, name || "<ANONYMOUS>");
return publicNS;
}
// 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 },
_lazy: { value: lazy, writable: true, enumerable: true, configurable: true },
_moduleDefine: { value: moduleDefine, writable: true, enumerable: true, configurable: true }
});
})();
(function () {
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 () { };
_BaseCoreUtils.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);
_BaseCoreUtils.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
});
})();
return {
Namespace: _WinJS.Namespace,
Class: _WinJS.Class
};
});
_winjs("WinJS/Core/_ErrorFromName", ["WinJS/Core/_Base"], function errorsInit(_Base) {
"use strict";
var ErrorFromName = _Base.Class.derive(Error, function (name, message) {
/// <signature helpKeyword="WinJS.ErrorFromName">
/// <summary locid="WinJS.ErrorFromName">
/// Creates an Error object with the specified name and message properties.
/// </summary>
/// <param name="name" type="String" locid="WinJS.ErrorFromName_p:name">The name of this error. The name is meant to be consumed programmatically and should not be localized.</param>
/// <param name="message" type="String" optional="true" locid="WinJS.ErrorFromName_p:message">The message for this error. The message is meant to be consumed by humans and should be localized.</param>
/// <returns type="Error" locid="WinJS.ErrorFromName_returnValue">Error instance with .name and .message properties populated</returns>
/// </signature>
this.name = name;
this.message = message || name;
}, {
/* empty */
}, {
supportedForProcessing: false,
});
_Base.Namespace.define("WinJS", {
// ErrorFromName establishes a simple pattern for returning error codes.
//
ErrorFromName: ErrorFromName
});
return ErrorFromName;
});
_winjs("WinJS/Core/_Events", ["exports","WinJS/Core/_Base"], function eventsInit(exports, _Base) {
"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() {
/// <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 = _Base.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 is 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;
}
}
}
}
};
_Base.Namespace._moduleDefine(exports, "WinJS.Utilities", {
_createEventProperty: createEventProperty,
createEventProperties: createEventProperties,
eventMixin: eventMixin
});
});
_winjs("WinJS/Core/_Trace", ["WinJS/Core/_Global"], function traceInit(_Global) {
"use strict";
function nop(v) {
return v;
}
return {
_traceAsyncOperationStarting: (_Global.Debug && _Global.Debug.msTraceAsyncOperationStarting && _Global.Debug.msTraceAsyncOperationStarting.bind(_Global.Debug)) || nop,
_traceAsyncOperationCompleted: (_Global.Debug && _Global.Debug.msTraceAsyncOperationCompleted && _Global.Debug.msTraceAsyncOperationCompleted.bind(_Global.Debug)) || nop,
_traceAsyncCallbackStarting: (_Global.Debug && _Global.Debug.msTraceAsyncCallbackStarting && _Global.Debug.msTraceAsyncCallbackStarting.bind(_Global.Debug)) || nop,
_traceAsyncCallbackCompleted: (_Global.Debug && _Global.Debug.msTraceAsyncCallbackCompleted && _Global.Debug.msTraceAsyncCallbackCompleted.bind(_Global.Debug)) || nop
};
});
_winjs("WinJS/Promise/_StateMachine", ["WinJS/Core/_Global","WinJS/Core/_BaseCoreUtils","WinJS/Core/_Base","WinJS/Core/_ErrorFromName","WinJS/Core/_Events","WinJS/Core/_Trace"], function promiseStateMachineInit(_Global, _BaseCoreUtils, _Base, _ErrorFromName, _Events, _Trace) {
"use strict";
_Global.Debug && (_Global.Debug.setNonUserCodeExceptions = true);
var ListenerType = _Base.Class.mix(_Base.Class.define(null, { /*empty*/ }, { supportedForProcessing: false }), _Events.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 _() { }
// 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;
// We can special case our own intermediate promises which are not in a
// terminal state by just pushing this promise as a listener without
// having to create new indirection functions
if (waitedUpon instanceof ThenPromise &&
waitedUpon._state !== state_error &&
waitedUpon._state !== state_success) {
pushListener(waitedUpon, { promise: promise });
} else {
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.shift();
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.shift();
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 = _Base.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) {
var asyncOpID = _Trace._traceAsyncOperationStarting("WinJS.Promise.done");
pushListener(promise, { c: onComplete, e: onError, p: onProgress, asyncOpID: asyncOpID });
}
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;
_Trace._traceAsyncOperationCompleted(listener.asyncOpID, _Global.Debug && _Global.Debug.MS_ASYNC_OP_STATUS_SUCCESS);
if (target) {
_Trace._traceAsyncCallbackStarting(listener.asyncOpID);
try {
target._setCompleteValue(onComplete ? onComplete(value) : value);
} catch (ex) {
target._setExceptionValue(ex);
} finally {
_Trace._traceAsyncCallbackCompleted();
}
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;
var errorID = _Global.Debug && (value && value.name === canceledName ? _Global.Debug.MS_ASYNC_OP_STATUS_CANCELED : _Global.Debug.MS_ASYNC_OP_STATUS_ERROR);
_Trace._traceAsyncOperationCompleted(listener.asyncOpID, errorID);
if (target) {
var asyncCallbackStarted = false;
try {
if (onError) {
_Trace._traceAsyncCallbackStarting(listener.asyncOpID);
asyncCallbackStarted = true;
if (!onError.handlesOnError) {
callonerror(target, value, detailsForHandledError, promise, onError);
}
target._setCompleteValue(onError(value));
} else {
target._setChainedErrorValue(value, promise);
}
} catch (ex) {
target._setExceptionValue(ex);
} finally {
if (asyncCallbackStarted) {
_Trace._traceAsyncCallbackCompleted();
}
}
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);
var asyncOpID = _Trace._traceAsyncOperationStarting("WinJS.Promise.then");
pushListener(promise, { promise: result, c: onComplete, e: onError, p: onProgress, asyncOpID: asyncOpID });
return result;
}
//
// Internal implementation detail promise, ThenPromise is created when a promise needs
// to be returned from a then() method.
//
var ThenPromise = _Base.Class.derive(PromiseStateMachine,
function (creator) {
if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.thenPromise))) {
this._stack = 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 = _Base.Class.define(
function ErrorPromise_ctor(value) {
if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.errorPromise))) {
this._stack = 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
//
Promise._doneHandler(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 = _Base.Class.derive(ErrorPromise,
function ExceptionPromise_ctor(value) {
if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.exceptionPromise))) {
this._stack = Promise._getStack();
}
this._value = value;
callonerror(this, value, detailsForException);
}, {
/* empty */
}, {
supportedForProcessing: false
}
);
var CompletePromise = _Base.Class.define(
function CompletePromise_ctor(value) {
if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.completePromise))) {
this._stack = 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
Promise._doneHandler(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 Promise(
function (c) {
if (timeoutMS) {
id = _Global.setTimeout(c, timeoutMS);
} else {
_BaseCoreUtils._setImmediate(c);
}
},
function () {
if (id) {
_Global.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 = _Base.Class.derive(PromiseStateMachine,
function Promise_ctor(init, oncancel) {
/// <signature helpKeyword="WinJS.Promise">
/// <summary locid="WinJS.Promise">
/// A promise provides a mechanism to schedule work to be done on a value that
/// has not yet been computed. It is a convenient abstraction for managing
/// interactions with asynchronous APIs.
/// </summary>
/// <param name="init" type="Function" locid="WinJS.Promise_p:init">
/// The function that is called during construction of the promise. The function
/// is given three arguments (complete, error, progress). Inside this function
/// you should add event listeners for the notifications supported by this value.
/// </param>
/// <param name="oncancel" optional="true" locid="WinJS.Promise_p:oncancel">
/// The function to call if a consumer of this promise wants
/// to cancel its undone work. Promises are not required to
/// support cancellation.
/// </param>
/// </signature>
if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.promise))) {
this._stack = Promise._getStack();
}
this._oncancel = oncancel;
this._setState(state_created);
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 () {
// BEGIN monaco change
try {
if (this._oncancel) {
this._oncancel();
} else {
throw new Error('Promise did not implement oncancel');
}
} catch (ex) {
// Access fields to get them created
var msg = ex.message;
var stack = ex.stack;
promiseEventListeners.dispatchEvent('error', ex);
}
// END monaco change
},
_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) {
var keys = Object.keys(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(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 _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(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 (_Global.Debug && _Global.Debug.debuggerEnabled) {
try { throw new Error(); } catch (e) { return e.stack; }
}
},
_cancelBlocker: function Promise__cancelBlocker(input, oncancel) {
//
// Returns a promise which on cancelation will still result in downstream cancelation while
// protecting the promise 'input' from being canceled which has the effect of allowing
// 'input' to be shared amoung various consumers.
//
if (!Promise.is(input)) {
return Promise.wrap(input);
}
var complete;
var error;
var output = new Promise(
function (c, e) {
complete = c;
error = e;
},
function () {
complete = null;
error = null;
oncancel && oncancel();
}
);
input.then(
function (v) { complete && complete(v); },
function (e) { error && error(e); }
);
return output;
},
}
);
Object.defineProperties(Promise, _Events.createEventProperties(errorET));
Promise._doneHandler = function (value) {
_BaseCoreUtils._setImmediate(function Promise_done_rethrow() {
throw value;
});
};
return {
PromiseStateMachine: PromiseStateMachine,
Promise: Promise,
state_created: state_created
};
});
_winjs("WinJS/Promise", ["WinJS/Core/_Base","WinJS/Promise/_StateMachine"], function promiseInit( _Base, _StateMachine) {
"use strict";
_Base.Namespace.define("WinJS", {
Promise: _StateMachine.Promise
});
return _StateMachine.Promise;
});
var exported = _modules["WinJS/Core/_WinJS"];
if (typeof exports === 'undefined' && typeof define === 'function' && define.amd) {
define([], exported);
} else {
module.exports = exported;
}
})();
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册