Browse Source

Merge branch 'more-polyfills'

Add some more polyfills: Object.assign() and Performance.now().

The RegExp.prototype.compile() polyfill cannot be implemented at the moment
because it needs to overwrite some RegExp instance properties which are
currently protected.
v1.0-maintenance
Sami Vaarala 10 years ago
parent
commit
5dbab265e8
  1. 2
      RELEASES.txt
  2. 4
      polyfills/console-minimal.js
  3. 45
      polyfills/object-assign.js
  4. 4
      polyfills/object-prototype-definegetter.js
  5. 4
      polyfills/object-prototype-definesetter.js
  6. 25
      polyfills/performance-now.js
  7. 65
      polyfills/regexp-prototype-compile.js
  8. 2
      util/make_dist.sh

2
RELEASES.txt

@ -515,6 +515,8 @@ Planned
* Make objects and functions defined by included polyfills non-enumerable so
that they don't enumerate e.g. in a for-in loop
* A few more polyfills.
1.0.0 (2014-08-XX)
------------------

4
polyfills/console-minimal.js

@ -1,3 +1,7 @@
/*
* Minimal console.log() polyfill
*/
if (typeof console === 'undefined') {
Object.defineProperty(this, 'console', {
value: {}, writable: true, enumerable: false, configurable: true

45
polyfills/object-assign.js

@ -0,0 +1,45 @@
/*
* Object.assign(), described in E6 Section 19.1.2.1
*
* https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign
*/
if (typeof Object.assign === 'undefined') {
Object.defineProperty(Object, 'assign', {
value: function (target) {
var i, n, j, m, k;
var source, keys;
var gotError;
var pendingError;
if (target == null) {
throw new Exception('target null or undefined');
}
for (i = 1, n = arguments.length; i < n; i++) {
source = arguments[i];
if (source == null) {
continue; // null or undefined
}
source = Object(source);
keys = Object.keys(source); // enumerable own keys
for (j = 0, m = keys.length; j < m; j++) {
k = keys[j];
try {
target[k] = source[k];
} catch (e) {
if (!gotError) {
gotError = true;
pendingError = e;
}
}
}
}
if (gotError) {
throw pendingError;
}
}, writable: true, enumerable: false, configurable: true
});
}

4
polyfills/object-prototype-definegetter.js

@ -1,3 +1,7 @@
/*
* Object.prototype.__defineGetter__ polyfill
*/
if (typeof Object.prototype.__defineGetter__ === 'undefined') {
Object.defineProperty(Object.prototype, '__defineGetter__', {
value: function (n, f) {

4
polyfills/object-prototype-definesetter.js

@ -1,3 +1,7 @@
/*
* Object.prototype.__defineSetter__ polyfill
*/
if (typeof Object.prototype.__defineSetter__ === 'undefined') {
Object.defineProperty(Object.prototype, '__defineSetter__', {
value: function (n, f) {

25
polyfills/performance-now.js

@ -0,0 +1,25 @@
/*
* Performance.now() polyfill
*
* http://www.w3.org/TR/hr-time/#sec-high-resolution-time
*
* Dummy implementation which uses the Date built-in and has no higher
* resolution. If/when Duktape has a built-in high resolution timer
* interface, reimplement this.
*/
var _perfNowZeroTime = Date.now();
if (typeof Performance === 'undefined') {
Object.defineProperty(this, 'Performance', {
value: {},
writable: true, enumerable: false, configurable: true
});
}
if (typeof Performance.now === 'undefined') {
Object.defineProperty(Performance, 'now', {
value: function () {
return Date.now() - _perfNowZeroTime;
}, writable: true, enumerable: false, configurable: true
});
}

65
polyfills/regexp-prototype-compile.js

@ -0,0 +1,65 @@
/*
* RegExp.prototype.compile() polyfill, described in E6 Annex B:
*
* https://people.mozilla.org/~jorendorff/es6-draft.html#sec-regexp.prototype.compile
*
* See also:
*
* http://mozilla.6506.n7.nabble.com/RegExp-prototype-compile-and-RegExp-instance-properties-td270408.html
*
* This polyfill cannot be implemented in terms of standard E5 because it
* needs to reinitialize the internal state of a RegExp instance. To do
* that, we access the Duktape internal properties directly, which is
* quite fragile.
*
* Avoid storing a public copy of Duktape or some internal property name in
* the global object. This could subvert user sandboxing.
*/
(function () {
var propBytecode = Duktape.dec('hex', 'ff62797465636f6465'); // \xFFbytecode
if (typeof RegExp.prototype.compile !== 'undefined') {
return;
}
Object.defineProperty(RegExp.prototype, 'compile', {
value: function (pattern, flags) {
var newBytecode, tmpRegexp;
if (typeof this !== 'object' || !(propBytecode in this)) {
throw new TypeError('invalid this binding');
}
// FIXME: property attributes prevent this approach from working
// right now. The properties we'd need to modify are non-writable
// and non-configurable:
//
// \xffbytecode
// source
// global
// ignoreCase
// multiline
//
// The property attributes can be relaxed, or the properties can
// be made accessors backing to the regexp bytecode, see Ditz
// issues: 0f2c246cadbb3b3913b75dc7e890ee4e7d336a1a and
// f8396fbcc36db4610fec5ad5a7d7a8f471d084a4.
if (typeof pattern === 'object' && (propBytecode in pattern)) {
this[propBytecode] = pattern[propBytecode];
} else {
tmpRegexp = new RegExp(pattern, flags);
this[propBytecode] = tmpRegexp[propBytecode];
}
//this.source
//this.global
//this.ignoreCase
//this.multiline
this.lastIndex = 0;
return this;
}, writable: true, enumerable: false, configurable: true
});
throw new Error('RegExp.prototype.compile() polyfill incomplete');
})();

2
util/make_dist.sh

@ -188,6 +188,8 @@ for i in \
console-minimal.js \
object-prototype-definegetter.js \
object-prototype-definesetter.js \
object-assign.js \
performance-now.js \
; do
cp polyfills/$i $DIST/polyfills/
done

Loading…
Cancel
Save