Merge pull request #654 from webcomponents/ie-compat

Enhance compatibility with IE
This commit is contained in:
Steve Orvell
2016-12-01 11:26:11 -08:00
committed by GitHub
5 changed files with 259 additions and 12 deletions

View File

@@ -0,0 +1,186 @@
(function() {
if (!window.Promise) {
function MakePromise (asap) {
function Promise(fn) {
if (typeof this !== 'object' || typeof fn !== 'function') throw new TypeError();
this._state = null;
this._value = null;
this._deferreds = []
doResolve(fn, resolve.bind(this), reject.bind(this));
}
function handle(deferred) {
var me = this;
if (this._state === null) {
this._deferreds.push(deferred);
return
}
asap(function() {
var cb = me._state ? deferred.onFulfilled : deferred.onRejected
if (typeof cb !== 'function') {
(me._state ? deferred.resolve : deferred.reject)(me._value);
return;
}
var ret;
try {
ret = cb(me._value);
}
catch (e) {
deferred.reject(e);
return;
}
deferred.resolve(ret);
})
}
function resolve(newValue) {
try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
if (newValue === this) throw new TypeError();
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then;
if (typeof then === 'function') {
doResolve(then.bind(newValue), resolve.bind(this), reject.bind(this));
return;
}
}
this._state = true;
this._value = newValue;
finale.call(this);
} catch (e) { reject.call(this, e); }
}
function reject(newValue) {
this._state = false;
this._value = newValue;
finale.call(this);
}
function finale() {
for (var i = 0, len = this._deferreds.length; i < len; i++) {
handle.call(this, this._deferreds[i]);
}
this._deferreds = null;
}
/**
* Take a potentially misbehaving resolver function and make sure
* onFulfilled and onRejected are only called once.
*
* Makes no guarantees about asynchrony.
*/
function doResolve(fn, onFulfilled, onRejected) {
var done = false;
try {
fn(function (value) {
if (done) return;
done = true;
onFulfilled(value);
}, function (reason) {
if (done) return;
done = true;
onRejected(reason);
})
} catch (ex) {
if (done) return;
done = true;
onRejected(ex);
}
}
Promise.prototype['catch'] = function (onRejected) {
return this.then(null, onRejected);
};
Promise.prototype.then = function(onFulfilled, onRejected) {
var me = this;
return new Promise(function(resolve, reject) {
handle.call(me, {
onFulfilled: onFulfilled,
onRejected: onRejected,
resolve: resolve,
reject: reject
});
})
};
Promise.resolve = function (value) {
if (value && typeof value === 'object' && value.constructor === Promise) {
return value;
}
return new Promise(function (resolve) {
resolve(value);
});
};
Promise.reject = function (value) {
return new Promise(function (resolve, reject) {
reject(value);
});
};
return Promise;
}
function makeAsync() {
var twiddle = document.createTextNode('');
var content = 0;
return function(callback) {
// To preserve timing with Promise microtasks
// we create a new observer for every callback.
var observer = new MutationObserver(function(mxns) {
observer.disconnect();
callback();
});
observer.observe(twiddle, {characterData: true});
twiddle.textContent = content++;
}
}
window.Promise = MakePromise(makeAsync());
window.Promise.all = function () {
var args = Array.prototype.slice.call(arguments.length === 1 && Array.isArray(arguments[0]) ? arguments[0] : arguments);
return new Promise(function (resolve, reject) {
if (args.length === 0) return resolve([]);
var remaining = args.length;
function res(i, val) {
try {
if (val && (typeof val === 'object' || typeof val === 'function')) {
var then = val.then;
if (typeof then === 'function') {
then.call(val, function (val) { res(i, val) }, reject);
return;
}
}
args[i] = val;
if (--remaining === 0) {
resolve(args);
}
} catch (ex) {
reject(ex);
}
}
for (var i = 0; i < args.length; i++) {
res(i, args[i]);
}
});
};
window.Promise.race = function (values) {
return new Promise(function (resolve, reject) {
for(var i = 0, len = values.length; i < len; i++) {
values[i].then(resolve, reject);
}
});
};
}
})();

View File

@@ -5,7 +5,11 @@
"../MutationObserver/MutationObserver.js",
"../Template/Template.js",
"../HTMLImports/build.json",
"../CustomElements/build.json",
"Promise.js",
"../../custom-elements/custom-elements.min.js",
"../../shadydom/shadydom.min.js",
"../../shadycss/shadycss.min.js",
"lang.js",
"dom.js",
"unresolved.js"
]

View File

@@ -99,7 +99,33 @@
e.initEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable));
return e;
};
if (origEvent) {
for (var i in origEvent) {
window.Event[i] = origEvent[i];
}
}
window.Event.prototype = origEvent.prototype;
}
if (!window.MouseEvent || isIE && (typeof window.MouseEvent !== 'function')) {
var origMouseEvent = window.MouseEvent;
window.MouseEvent = function(inType, params) {
params = params || {};
var e = document.createEvent('MouseEvent');
e.initMouseEvent(inType,
Boolean(params.bubbles), Boolean(params.cancelable),
params.view || window, params.detail,
params.screenX, params.screenY, params.clientX, params.clientY,
params.ctrlKey, params.altKey, params.shiftKey, params.metaKey,
params.button, params.relatedTarget);
return e;
};
if (origMouseEvent) {
for (var i in origMouseEvent) {
window.MouseEvent[i] = origMouseEvent[i];
}
}
window.MouseEvent.prototype = origMouseEvent.prototype;
}
})(window.WebComponents);

View File

@@ -10,18 +10,47 @@
(function(scope) {
// Old versions of iOS do not have bind.
'use strict';
if (!Function.prototype.bind) {
Function.prototype.bind = function(scope) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
return function() {
var args2 = args.slice();
args2.push.apply(args2, arguments);
return self.apply(scope, args2);
// Old versions of iOS do not have bind.
if (!Function.prototype.bind) {
Function.prototype.bind = function(scope) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
return function() {
var args2 = args.slice();
args2.push.apply(args2, arguments);
return self.apply(scope, args2);
};
};
};
}
}
// ES6 stuff
if (!Array.from) {
Array.from = function (object) {
return [].slice.call(object);
};
}
if (!Object.assign) {
function assign(target, source) {
var n$ = Object.getOwnPropertyNames(source);
for (var i=0, p; i < n$.length; i++) {
p = n$[i];
target[p] = source[p];
}
}
Object.assign = function(target, sources) {
var args = [].slice.call(arguments, 1);
for (var i=0, s; i < args.length; i++) {
s = args[i];
if (s) {
assign(target, s);
}
}
return target;
}
}
})(window.WebComponents);

View File

@@ -54,12 +54,14 @@
'WeakMap/WeakMap.js',
'Template/Template.js',
'HTMLImports/HTMLImports.js',
'WebComponents/Promise.js',
'WebComponents/pre-polyfill.js',
'../../custom-elements/custom-elements.min.js',
'../../shadydom/shadydom.min.js',
'../../shadycss/shadycss.min.js',
'WebComponents/post-polyfill.js',
// these scripts are loaded here due to polyfill timing issues
'WebComponents/lang.js',
'WebComponents/dom.js',
'WebComponents/unresolved.js'
];