Selaa lähdekoodia

Associated with #3600

David Catuhe 7 vuotta sitten
vanhempi
commit
f7faaa0e58

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 4858 - 4850
Playground/babylon.d.txt


+ 12 - 2
Tools/Gulp/gulpfile.js

@@ -60,7 +60,12 @@ var tsConfig = {
     noUnusedLocals: true,
     strictNullChecks: true,
     strictFunctionTypes: true,
-    types: []
+    types: [],
+    lib: [
+        "dom",
+        "es2015.promise",
+        "es5"
+    ]
 };
 var tsProject = typescript.createProject(tsConfig);
 
@@ -76,7 +81,12 @@ var externalTsConfig = {
     noImplicitThis: true,
     noUnusedLocals: true,
     strictNullChecks: true,
-    types: []
+    types: [],
+    lib: [
+        "dom",
+        "es2015.promise",
+        "es5"
+    ]
 };
 
 var minimist = require("minimist");

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 10778 - 10775
dist/preview release/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 44 - 44
dist/preview release/babylon.js


+ 53 - 7
dist/preview release/babylon.max.js

@@ -8280,10 +8280,19 @@ var BABYLON;
         PromiseStates[PromiseStates["Fulfilled"] = 1] = "Fulfilled";
         PromiseStates[PromiseStates["Rejected"] = 2] = "Rejected";
     })(PromiseStates || (PromiseStates = {}));
+    var FulFillmentAgregator = /** @class */ (function () {
+        function FulFillmentAgregator() {
+            this.count = 0;
+            this.target = 0;
+            this.results = [];
+        }
+        return FulFillmentAgregator;
+    }());
     var InternalPromise = /** @class */ (function () {
         function InternalPromise(resolver) {
             var _this = this;
             this._state = PromiseStates.Pending;
+            this._rejectWasConsumed = false;
             if (!resolver) {
                 return;
             }
@@ -8335,18 +8344,17 @@ var BABYLON;
             newPromise._onRejected = onRejected;
             // Composition
             this._child = newPromise;
-            switch (this._state) {
-                case PromiseStates.Fulfilled:
+            if (this._state !== PromiseStates.Pending) {
+                if (this._state === PromiseStates.Fulfilled || this._rejectWasConsumed) {
                     var returnedPromise = newPromise._resolve(this._result);
                     if (returnedPromise) {
                         newPromise._child = returnedPromise;
                         newPromise = returnedPromise;
                     }
-                    break;
-                case PromiseStates.Rejected:
+                }
+                else {
                     newPromise._reject(this._reason);
-                    newPromise._state = PromiseStates.Fulfilled;
-                    break;
+                }
             }
             return newPromise;
         };
@@ -8373,9 +8381,15 @@ var BABYLON;
             this._reason = reason;
             if (this._onRejected) {
                 this._onRejected(reason);
+                this._rejectWasConsumed = true;
             }
             if (this._child) {
-                this._child._resolve(null);
+                if (this._rejectWasConsumed) {
+                    this._child._resolve(null);
+                }
+                else {
+                    this._child._reject(reason);
+                }
             }
         };
         InternalPromise.resolve = function (value) {
@@ -8383,11 +8397,43 @@ var BABYLON;
             newPromise._resolve(value);
             return newPromise;
         };
+        InternalPromise._RegisterForFulfillment = function (promise, agregator, index) {
+            promise.then(function (value) {
+                agregator.results[index] = value;
+                agregator.count++;
+                if (agregator.count === agregator.target) {
+                    agregator.rootPromise._resolve(agregator.results);
+                }
+                return null;
+            }, function (reason) {
+                if (!agregator.rootPromise.isRejected) {
+                    agregator.rootPromise._reject(reason);
+                }
+            });
+        };
+        InternalPromise.all = function (promises) {
+            var newPromise = new InternalPromise();
+            var agregator = new FulFillmentAgregator();
+            agregator.target = promises.length;
+            agregator.rootPromise = newPromise;
+            for (var index = 0; index < promises.length; index++) {
+                InternalPromise._RegisterForFulfillment(promises[index], agregator, index);
+            }
+            return newPromise;
+        };
         return InternalPromise;
     }());
+    /**
+     * Helper class that provides a small promise polyfill
+     */
     var PromisePolyfill = /** @class */ (function () {
         function PromisePolyfill() {
         }
+        /**
+         * Static function used to check if the polyfill is required
+         * If this is the case then the function will inject the polyfill to window.Promise
+         * @param force defines a boolean used to force the injection (mostly for testing purposes)
+         */
         PromisePolyfill.Apply = function (force) {
             if (force === void 0) { force = false; }
             if (force || typeof Promise === 'undefined') {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 44 - 44
dist/preview release/babylon.worker.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1001 - 993
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 44 - 44
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 70 - 24
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -8280,10 +8280,19 @@ var BABYLON;
         PromiseStates[PromiseStates["Fulfilled"] = 1] = "Fulfilled";
         PromiseStates[PromiseStates["Rejected"] = 2] = "Rejected";
     })(PromiseStates || (PromiseStates = {}));
-    var Promise = /** @class */ (function () {
-        function Promise(resolver) {
+    var FulFillmentAgregator = /** @class */ (function () {
+        function FulFillmentAgregator() {
+            this.count = 0;
+            this.target = 0;
+            this.results = [];
+        }
+        return FulFillmentAgregator;
+    }());
+    var InternalPromise = /** @class */ (function () {
+        function InternalPromise(resolver) {
             var _this = this;
             this._state = PromiseStates.Pending;
+            this._rejectWasConsumed = false;
             if (!resolver) {
                 return;
             }
@@ -8298,59 +8307,58 @@ var BABYLON;
                 this._reject(e.message);
             }
         }
-        Object.defineProperty(Promise.prototype, "state", {
+        Object.defineProperty(InternalPromise.prototype, "state", {
             get: function () {
                 return this._state;
             },
             enumerable: true,
             configurable: true
         });
-        Promise.prototype.isFulfilled = function () {
+        InternalPromise.prototype.isFulfilled = function () {
             return this._state === PromiseStates.Fulfilled;
         };
-        Promise.prototype.isRejected = function () {
+        InternalPromise.prototype.isRejected = function () {
             return this._state === PromiseStates.Rejected;
         };
-        Promise.prototype.isPending = function () {
+        InternalPromise.prototype.isPending = function () {
             return this._state === PromiseStates.Pending;
         };
-        Promise.prototype.value = function () {
+        InternalPromise.prototype.value = function () {
             if (!this.isFulfilled()) {
                 throw new Error("Promise is not fulfilled");
             }
             return this._result;
         };
-        Promise.prototype.reason = function () {
+        InternalPromise.prototype.reason = function () {
             if (!this.isRejected()) {
                 throw new Error("Promise is not rejected");
             }
             return this._reason;
         };
-        Promise.prototype.catch = function (onRejected) {
+        InternalPromise.prototype.catch = function (onRejected) {
             return this.then(undefined, onRejected);
         };
-        Promise.prototype.then = function (onFulfilled, onRejected) {
-            var newPromise = new Promise();
+        InternalPromise.prototype.then = function (onFulfilled, onRejected) {
+            var newPromise = new InternalPromise();
             newPromise._onFulfilled = onFulfilled;
             newPromise._onRejected = onRejected;
             // Composition
             this._child = newPromise;
-            switch (this._state) {
-                case PromiseStates.Fulfilled:
+            if (this._state !== PromiseStates.Pending) {
+                if (this._state === PromiseStates.Fulfilled || this._rejectWasConsumed) {
                     var returnedPromise = newPromise._resolve(this._result);
                     if (returnedPromise) {
                         newPromise._child = returnedPromise;
                         newPromise = returnedPromise;
                     }
-                    break;
-                case PromiseStates.Rejected:
+                }
+                else {
                     newPromise._reject(this._reason);
-                    newPromise._state = PromiseStates.Fulfilled;
-                    break;
+                }
             }
             return newPromise;
         };
-        Promise.prototype._resolve = function (value) {
+        InternalPromise.prototype._resolve = function (value) {
             try {
                 this._state = PromiseStates.Fulfilled;
                 this._result = value;
@@ -8368,31 +8376,69 @@ var BABYLON;
             }
             return null;
         };
-        Promise.prototype._reject = function (reason) {
+        InternalPromise.prototype._reject = function (reason) {
             this._state = PromiseStates.Rejected;
             this._reason = reason;
             if (this._onRejected) {
                 this._onRejected(reason);
+                this._rejectWasConsumed = true;
             }
             if (this._child) {
-                this._child._resolve(null);
+                if (this._rejectWasConsumed) {
+                    this._child._resolve(null);
+                }
+                else {
+                    this._child._reject(reason);
+                }
             }
         };
-        Promise.resolve = function (value) {
-            var newPromise = new Promise();
+        InternalPromise.resolve = function (value) {
+            var newPromise = new InternalPromise();
             newPromise._resolve(value);
             return newPromise;
         };
-        return Promise;
+        InternalPromise._RegisterForFulfillment = function (promise, agregator, index) {
+            promise.then(function (value) {
+                agregator.results[index] = value;
+                agregator.count++;
+                if (agregator.count === agregator.target) {
+                    agregator.rootPromise._resolve(agregator.results);
+                }
+                return null;
+            }, function (reason) {
+                if (!agregator.rootPromise.isRejected) {
+                    agregator.rootPromise._reject(reason);
+                }
+            });
+        };
+        InternalPromise.all = function (promises) {
+            var newPromise = new InternalPromise();
+            var agregator = new FulFillmentAgregator();
+            agregator.target = promises.length;
+            agregator.rootPromise = newPromise;
+            for (var index = 0; index < promises.length; index++) {
+                InternalPromise._RegisterForFulfillment(promises[index], agregator, index);
+            }
+            return newPromise;
+        };
+        return InternalPromise;
     }());
+    /**
+     * Helper class that provides a small promise polyfill
+     */
     var PromisePolyfill = /** @class */ (function () {
         function PromisePolyfill() {
         }
+        /**
+         * Static function used to check if the polyfill is required
+         * If this is the case then the function will inject the polyfill to window.Promise
+         * @param force defines a boolean used to force the injection (mostly for testing purposes)
+         */
         PromisePolyfill.Apply = function (force) {
             if (force === void 0) { force = false; }
             if (force || typeof Promise === 'undefined') {
                 var root = window;
-                root.Promise = Promise;
+                root.Promise = InternalPromise;
             }
         };
         return PromisePolyfill;

+ 70 - 24
dist/preview release/customConfigurations/minimalGLTFViewer/es6.js

@@ -8266,10 +8266,19 @@ var BABYLON;
         PromiseStates[PromiseStates["Fulfilled"] = 1] = "Fulfilled";
         PromiseStates[PromiseStates["Rejected"] = 2] = "Rejected";
     })(PromiseStates || (PromiseStates = {}));
-    var Promise = /** @class */ (function () {
-        function Promise(resolver) {
+    var FulFillmentAgregator = /** @class */ (function () {
+        function FulFillmentAgregator() {
+            this.count = 0;
+            this.target = 0;
+            this.results = [];
+        }
+        return FulFillmentAgregator;
+    }());
+    var InternalPromise = /** @class */ (function () {
+        function InternalPromise(resolver) {
             var _this = this;
             this._state = PromiseStates.Pending;
+            this._rejectWasConsumed = false;
             if (!resolver) {
                 return;
             }
@@ -8284,59 +8293,58 @@ var BABYLON;
                 this._reject(e.message);
             }
         }
-        Object.defineProperty(Promise.prototype, "state", {
+        Object.defineProperty(InternalPromise.prototype, "state", {
             get: function () {
                 return this._state;
             },
             enumerable: true,
             configurable: true
         });
-        Promise.prototype.isFulfilled = function () {
+        InternalPromise.prototype.isFulfilled = function () {
             return this._state === PromiseStates.Fulfilled;
         };
-        Promise.prototype.isRejected = function () {
+        InternalPromise.prototype.isRejected = function () {
             return this._state === PromiseStates.Rejected;
         };
-        Promise.prototype.isPending = function () {
+        InternalPromise.prototype.isPending = function () {
             return this._state === PromiseStates.Pending;
         };
-        Promise.prototype.value = function () {
+        InternalPromise.prototype.value = function () {
             if (!this.isFulfilled()) {
                 throw new Error("Promise is not fulfilled");
             }
             return this._result;
         };
-        Promise.prototype.reason = function () {
+        InternalPromise.prototype.reason = function () {
             if (!this.isRejected()) {
                 throw new Error("Promise is not rejected");
             }
             return this._reason;
         };
-        Promise.prototype.catch = function (onRejected) {
+        InternalPromise.prototype.catch = function (onRejected) {
             return this.then(undefined, onRejected);
         };
-        Promise.prototype.then = function (onFulfilled, onRejected) {
-            var newPromise = new Promise();
+        InternalPromise.prototype.then = function (onFulfilled, onRejected) {
+            var newPromise = new InternalPromise();
             newPromise._onFulfilled = onFulfilled;
             newPromise._onRejected = onRejected;
             // Composition
             this._child = newPromise;
-            switch (this._state) {
-                case PromiseStates.Fulfilled:
+            if (this._state !== PromiseStates.Pending) {
+                if (this._state === PromiseStates.Fulfilled || this._rejectWasConsumed) {
                     var returnedPromise = newPromise._resolve(this._result);
                     if (returnedPromise) {
                         newPromise._child = returnedPromise;
                         newPromise = returnedPromise;
                     }
-                    break;
-                case PromiseStates.Rejected:
+                }
+                else {
                     newPromise._reject(this._reason);
-                    newPromise._state = PromiseStates.Fulfilled;
-                    break;
+                }
             }
             return newPromise;
         };
-        Promise.prototype._resolve = function (value) {
+        InternalPromise.prototype._resolve = function (value) {
             try {
                 this._state = PromiseStates.Fulfilled;
                 this._result = value;
@@ -8354,31 +8362,69 @@ var BABYLON;
             }
             return null;
         };
-        Promise.prototype._reject = function (reason) {
+        InternalPromise.prototype._reject = function (reason) {
             this._state = PromiseStates.Rejected;
             this._reason = reason;
             if (this._onRejected) {
                 this._onRejected(reason);
+                this._rejectWasConsumed = true;
             }
             if (this._child) {
-                this._child._resolve(null);
+                if (this._rejectWasConsumed) {
+                    this._child._resolve(null);
+                }
+                else {
+                    this._child._reject(reason);
+                }
             }
         };
-        Promise.resolve = function (value) {
-            var newPromise = new Promise();
+        InternalPromise.resolve = function (value) {
+            var newPromise = new InternalPromise();
             newPromise._resolve(value);
             return newPromise;
         };
-        return Promise;
+        InternalPromise._RegisterForFulfillment = function (promise, agregator, index) {
+            promise.then(function (value) {
+                agregator.results[index] = value;
+                agregator.count++;
+                if (agregator.count === agregator.target) {
+                    agregator.rootPromise._resolve(agregator.results);
+                }
+                return null;
+            }, function (reason) {
+                if (!agregator.rootPromise.isRejected) {
+                    agregator.rootPromise._reject(reason);
+                }
+            });
+        };
+        InternalPromise.all = function (promises) {
+            var newPromise = new InternalPromise();
+            var agregator = new FulFillmentAgregator();
+            agregator.target = promises.length;
+            agregator.rootPromise = newPromise;
+            for (var index = 0; index < promises.length; index++) {
+                InternalPromise._RegisterForFulfillment(promises[index], agregator, index);
+            }
+            return newPromise;
+        };
+        return InternalPromise;
     }());
+    /**
+     * Helper class that provides a small promise polyfill
+     */
     var PromisePolyfill = /** @class */ (function () {
         function PromisePolyfill() {
         }
+        /**
+         * Static function used to check if the polyfill is required
+         * If this is the case then the function will inject the polyfill to window.Promise
+         * @param force defines a boolean used to force the injection (mostly for testing purposes)
+         */
         PromisePolyfill.Apply = function (force) {
             if (force === void 0) { force = false; }
             if (force || typeof Promise === 'undefined') {
                 var root = window;
-                root.Promise = Promise;
+                root.Promise = InternalPromise;
             }
         };
         return PromisePolyfill;

+ 53 - 7
dist/preview release/es6.js

@@ -8266,10 +8266,19 @@ var BABYLON;
         PromiseStates[PromiseStates["Fulfilled"] = 1] = "Fulfilled";
         PromiseStates[PromiseStates["Rejected"] = 2] = "Rejected";
     })(PromiseStates || (PromiseStates = {}));
+    var FulFillmentAgregator = /** @class */ (function () {
+        function FulFillmentAgregator() {
+            this.count = 0;
+            this.target = 0;
+            this.results = [];
+        }
+        return FulFillmentAgregator;
+    }());
     var InternalPromise = /** @class */ (function () {
         function InternalPromise(resolver) {
             var _this = this;
             this._state = PromiseStates.Pending;
+            this._rejectWasConsumed = false;
             if (!resolver) {
                 return;
             }
@@ -8321,18 +8330,17 @@ var BABYLON;
             newPromise._onRejected = onRejected;
             // Composition
             this._child = newPromise;
-            switch (this._state) {
-                case PromiseStates.Fulfilled:
+            if (this._state !== PromiseStates.Pending) {
+                if (this._state === PromiseStates.Fulfilled || this._rejectWasConsumed) {
                     var returnedPromise = newPromise._resolve(this._result);
                     if (returnedPromise) {
                         newPromise._child = returnedPromise;
                         newPromise = returnedPromise;
                     }
-                    break;
-                case PromiseStates.Rejected:
+                }
+                else {
                     newPromise._reject(this._reason);
-                    newPromise._state = PromiseStates.Fulfilled;
-                    break;
+                }
             }
             return newPromise;
         };
@@ -8359,9 +8367,15 @@ var BABYLON;
             this._reason = reason;
             if (this._onRejected) {
                 this._onRejected(reason);
+                this._rejectWasConsumed = true;
             }
             if (this._child) {
-                this._child._resolve(null);
+                if (this._rejectWasConsumed) {
+                    this._child._resolve(null);
+                }
+                else {
+                    this._child._reject(reason);
+                }
             }
         };
         InternalPromise.resolve = function (value) {
@@ -8369,11 +8383,43 @@ var BABYLON;
             newPromise._resolve(value);
             return newPromise;
         };
+        InternalPromise._RegisterForFulfillment = function (promise, agregator, index) {
+            promise.then(function (value) {
+                agregator.results[index] = value;
+                agregator.count++;
+                if (agregator.count === agregator.target) {
+                    agregator.rootPromise._resolve(agregator.results);
+                }
+                return null;
+            }, function (reason) {
+                if (!agregator.rootPromise.isRejected) {
+                    agregator.rootPromise._reject(reason);
+                }
+            });
+        };
+        InternalPromise.all = function (promises) {
+            var newPromise = new InternalPromise();
+            var agregator = new FulFillmentAgregator();
+            agregator.target = promises.length;
+            agregator.rootPromise = newPromise;
+            for (var index = 0; index < promises.length; index++) {
+                InternalPromise._RegisterForFulfillment(promises[index], agregator, index);
+            }
+            return newPromise;
+        };
         return InternalPromise;
     }());
+    /**
+     * Helper class that provides a small promise polyfill
+     */
     var PromisePolyfill = /** @class */ (function () {
         function PromisePolyfill() {
         }
+        /**
+         * Static function used to check if the polyfill is required
+         * If this is the case then the function will inject the polyfill to window.Promise
+         * @param force defines a boolean used to force the injection (mostly for testing purposes)
+         */
         PromisePolyfill.Apply = function (force) {
             if (force === void 0) { force = false; }
             if (force || typeof Promise === 'undefined') {

+ 2 - 2
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 8871,
+  "errors": 8794,
   "babylon.typedoc.json": {
-    "errors": 8871,
+    "errors": 8794,
     "AnimationKeyInterpolation": {
       "Enumeration": {
         "Comments": {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 44 - 44
dist/preview release/viewer/babylon.viewer.js


+ 64 - 16
src/Tools/babylon.promise.ts

@@ -6,13 +6,21 @@ module BABYLON {
         Rejected
     }
 
+    class FulFillmentAgregator<T> {
+        public count = 0;
+        public target = 0;
+        public rootPromise: InternalPromise<T>;
+        public results:any[] = [];
+    }
+
     class InternalPromise<T> {
         private _state = PromiseStates.Pending;
         private _result?: Nullable<T>;
-        private _reason: string;
+        private _reason: any;
         private _child: InternalPromise<T>;
         private _onFulfilled?: (fulfillment?: Nullable<T>) => Nullable<InternalPromise<T>>;
-        private _onRejected?: (reason: string) => void;
+        private _onRejected?: (reason: any) => void;
+        private _rejectWasConsumed = false;
 
         public get state(): PromiseStates {
             return this._state;
@@ -37,7 +45,7 @@ module BABYLON {
             return this._result;
         }     
         
-        public reason(): string {
+        public reason(): any {
             if (!this.isRejected()) {
                 throw new Error("Promise is not rejected");
             }
@@ -46,7 +54,7 @@ module BABYLON {
 
         public constructor(resolver?: (
             resolve:(value?: Nullable<T>) => void, 
-            reject: (reason: string) => void
+            reject: (reason: any) => void
         ) => void) {
 
             if (!resolver) {
@@ -56,7 +64,7 @@ module BABYLON {
             try {
                 resolver((value?: Nullable<T>) => {
                     this._resolve(value);
-                }, (reason: string) => {
+                }, (reason: any) => {
                     this._reject(reason);
                 });
             } catch(e) {
@@ -64,11 +72,11 @@ module BABYLON {
             }
         }
 
-        public catch(onRejected: (reason: string) => void): InternalPromise<T> {
+        public catch(onRejected: (reason: any) => void): InternalPromise<T> {
             return this.then(undefined, onRejected);
         }
 
-        public then(onFulfilled?: (fulfillment?: Nullable<T>) => Nullable<InternalPromise<T>>, onRejected?: (reason: string) => void): InternalPromise<T> {
+        public then(onFulfilled?: (fulfillment?: Nullable<T>) => Nullable<InternalPromise<T>>, onRejected?: (reason: any) => void): InternalPromise<T> {
             let newPromise = new InternalPromise<T>();
             newPromise._onFulfilled = onFulfilled;
             newPromise._onRejected = onRejected;
@@ -76,19 +84,17 @@ module BABYLON {
             // Composition
             this._child = newPromise;
 
-            switch (this._state) {
-                case PromiseStates.Fulfilled:
+            if (this._state !== PromiseStates.Pending) {
+                if (this._state === PromiseStates.Fulfilled || this._rejectWasConsumed) {
                     let returnedPromise = newPromise._resolve(this._result);
 
                     if (returnedPromise) {
                         newPromise._child = returnedPromise;
                         newPromise = returnedPromise;
                     }
-                    break;
-                case PromiseStates.Rejected:
+                } else {
                     newPromise._reject(this._reason);
-                    newPromise._state = PromiseStates.Fulfilled;
-                    break;
+                }
             }
 
             return newPromise;
@@ -116,16 +122,21 @@ module BABYLON {
             return null;
         }
 
-        private _reject(reason: string): void {
+        private _reject(reason: any): void {
             this._state = PromiseStates.Rejected;
             this._reason = reason;
 
             if (this._onRejected) {
                 this._onRejected(reason);
+                this._rejectWasConsumed = true;
             }
 
             if (this._child) {
-                this._child._resolve(null);
+                if (this._rejectWasConsumed) {
+                    this._child._resolve(null);
+                } else {
+                    this._child._reject(reason);
+                }
             }                
         }
 
@@ -136,10 +147,47 @@ module BABYLON {
 
             return newPromise;
         }
+
+        private static _RegisterForFulfillment<T>(promise: InternalPromise<T>, agregator: FulFillmentAgregator<T[]>, index: number) {
+            promise.then((value?: Nullable<T>) => {
+                agregator.results[index] = value;
+                agregator.count++;
+
+                if (agregator.count === agregator.target) {
+                    agregator.rootPromise._resolve(agregator.results);
+                }
+                return null;
+            }, (reason: any) => {
+                if (!agregator.rootPromise.isRejected) {
+                    agregator.rootPromise._reject(reason);
+                }
+            })
+        }
+
+        public static all<T>(promises: InternalPromise<T>[]): InternalPromise<T[]> {
+            let newPromise = new InternalPromise<T[]>();
+            let agregator = new FulFillmentAgregator<T[]>();
+            agregator.target = promises.length;
+            agregator.rootPromise = newPromise;
+
+            for(var index = 0; index < promises.length; index++) {
+                InternalPromise._RegisterForFulfillment(promises[index], agregator, index);
+            }
+
+            return newPromise;
+        }
     }
 
+    /**
+     * Helper class that provides a small promise polyfill
+     */
     export class PromisePolyfill {
-        public static Apply(force = false) {
+        /**
+         * Static function used to check if the polyfill is required
+         * If this is the case then the function will inject the polyfill to window.Promise
+         * @param force defines a boolean used to force the injection (mostly for testing purposes)
+         */
+        public static Apply(force = false): void {
             if (force || typeof Promise === 'undefined') {
                 let root:any = window;
                 root.Promise = InternalPromise;

+ 0 - 7
src/babylon.mixins.ts

@@ -169,10 +169,3 @@ interface EXT_disjoint_timer_query {
 interface WebGLUniformLocation {
     _currentState: any;
 }
-
-interface Promise<T> {
-    new (executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
-    then(onFulfilled?: (fulfillment?: BABYLON.Nullable<T>) => BABYLON.Nullable<Promise<T>>, onRejected?: (reason: string) => void): Promise<T>
-}
-
-declare var Promise: Promise<any>;

+ 6 - 1
src/tsconfig.json

@@ -14,6 +14,11 @@
     "noUnusedLocals": true,
     "strictNullChecks": true,
     "strictFunctionTypes": true,
-    "skipLibCheck": true
+    "skipLibCheck": true,
+    "lib": [
+        "dom",
+        "es2015.promise",
+        "es5"
+    ]
   }
 }

+ 84 - 5
tests/unit/babylon/promises/babylon.promises.tests.ts

@@ -30,12 +30,8 @@ describe('Babylon.Promise', () => {
         });
     });
 
-    /**
-     * This test is more an integration test than a regular unit test but highlights how to rely
-     * on the BABYLON.NullEngine in order to create complex test cases.
-     */
     describe('#Composition', () => {
-        it('should chain promises correctly', (done) => {
+        it('should chain promises correctly #1', (done) => {
             mocha.timeout(10000);
             var tempString = "";
             var p1 = new Promise((resolve, reject) => {
@@ -58,4 +54,87 @@ describe('Babylon.Promise', () => {
             });
         });
     });
+
+    describe('#Composition', () => {
+        it('should chain promises correctly #2', (done) => {
+            mocha.timeout(10000);
+            var tempString = "";
+            var p1 = new Promise((resolve, reject) => {
+                tempString = "Initial";
+            
+                resolve();
+            })
+            .then(() => {
+                tempString += " message";
+            })
+            .then(() => {
+                tempString += " to check promises";
+            })
+            .catch(() => {
+                tempString += " wrong!";
+            })
+            .then(() => {
+                expect(tempString).to.eq("Initial message to check promises");
+                done();
+            });
+        });
+    });    
+
+    describe('#Delayed', () => {
+        it('should chain promises correctly #3', (done) => {
+            mocha.timeout(10000);
+            var tempString = "";
+            function resolveLater(resolve, reject) {
+                setTimeout(function () {
+                    resolve(10);
+                }, 1000);
+            }
+            function rejectLater(resolve, reject) {
+                setTimeout(function () {
+                    reject(20);
+                }, 1000);
+            }
+        
+            var p1 = (<any>Promise).resolve('foo');
+            var p2 = p1.then(function () {
+                // Return promise here, that will be resolved to 10 after 1 second
+                return new Promise(resolveLater);
+            });
+            p2.then(function (v) {
+                tempString += 'resolved '+ v;  // "resolved", 10
+            }, function (e) {
+                // not called
+                tempString += 'rejected' + e;
+            });
+        
+            var p3 = p1.then(function () {
+                // Return promise here, that will be rejected with 20 after 1 second
+                return new Promise(rejectLater);
+            });
+            p3.then(function (v) {
+                // not called
+                tempString += 'resolved ' + v;
+            }, function (e) {
+                tempString += 'rejected ' + e; // "rejected", 20
+                expect(tempString).to.eq("resolved 10rejected 20");
+                done();
+            });
+        });
+    });    
+    
+    describe('#Promise.all', () => {
+        it('should agregate promises correctly', (done) => {
+            mocha.timeout(10000);
+            var promise1 = Promise.resolve(3);
+            var promise2 = new Promise(function(resolve, reject) {
+                setTimeout(resolve, 100, 'foo');
+            });
+            var promise3 = Promise.resolve(42);
+        
+            Promise.all([promise1, promise2, promise3]).then(function(values) {
+                values.should.deep.equal([3, "foo", 42]);
+                done();
+            });
+        });
+    });   
 });

+ 6 - 1
tests/unit/tsconfig.json

@@ -1,7 +1,12 @@
 {
     "compilerOptions": {
       "target": "es5",
-      "module": "none"
+      "module": "none",
+      "lib": [
+        "dom",
+        "es2015.promise",
+        "es5"
+    ]
     },
     "exclude": [
       "node_modules"