Skip to content

Commit 5dbab26

Browse files
committed
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.
2 parents 02c743a + 024d57c commit 5dbab26

8 files changed

Lines changed: 151 additions & 0 deletions

RELEASES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,8 @@ Planned
515515
* Make objects and functions defined by included polyfills non-enumerable so
516516
that they don't enumerate e.g. in a for-in loop
517517

518+
* A few more polyfills.
519+
518520
1.0.0 (2014-08-XX)
519521
------------------
520522

polyfills/console-minimal.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* Minimal console.log() polyfill
3+
*/
4+
15
if (typeof console === 'undefined') {
26
Object.defineProperty(this, 'console', {
37
value: {}, writable: true, enumerable: false, configurable: true

polyfills/object-assign.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Object.assign(), described in E6 Section 19.1.2.1
3+
*
4+
* https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign
5+
*/
6+
7+
if (typeof Object.assign === 'undefined') {
8+
Object.defineProperty(Object, 'assign', {
9+
value: function (target) {
10+
var i, n, j, m, k;
11+
var source, keys;
12+
var gotError;
13+
var pendingError;
14+
15+
if (target == null) {
16+
throw new Exception('target null or undefined');
17+
}
18+
19+
for (i = 1, n = arguments.length; i < n; i++) {
20+
source = arguments[i];
21+
if (source == null) {
22+
continue; // null or undefined
23+
}
24+
source = Object(source);
25+
keys = Object.keys(source); // enumerable own keys
26+
27+
for (j = 0, m = keys.length; j < m; j++) {
28+
k = keys[j];
29+
try {
30+
target[k] = source[k];
31+
} catch (e) {
32+
if (!gotError) {
33+
gotError = true;
34+
pendingError = e;
35+
}
36+
}
37+
}
38+
}
39+
40+
if (gotError) {
41+
throw pendingError;
42+
}
43+
}, writable: true, enumerable: false, configurable: true
44+
});
45+
}

polyfills/object-prototype-definegetter.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* Object.prototype.__defineGetter__ polyfill
3+
*/
4+
15
if (typeof Object.prototype.__defineGetter__ === 'undefined') {
26
Object.defineProperty(Object.prototype, '__defineGetter__', {
37
value: function (n, f) {

polyfills/object-prototype-definesetter.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* Object.prototype.__defineSetter__ polyfill
3+
*/
4+
15
if (typeof Object.prototype.__defineSetter__ === 'undefined') {
26
Object.defineProperty(Object.prototype, '__defineSetter__', {
37
value: function (n, f) {

polyfills/performance-now.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Performance.now() polyfill
3+
*
4+
* http://www.w3.org/TR/hr-time/#sec-high-resolution-time
5+
*
6+
* Dummy implementation which uses the Date built-in and has no higher
7+
* resolution. If/when Duktape has a built-in high resolution timer
8+
* interface, reimplement this.
9+
*/
10+
11+
var _perfNowZeroTime = Date.now();
12+
13+
if (typeof Performance === 'undefined') {
14+
Object.defineProperty(this, 'Performance', {
15+
value: {},
16+
writable: true, enumerable: false, configurable: true
17+
});
18+
}
19+
if (typeof Performance.now === 'undefined') {
20+
Object.defineProperty(Performance, 'now', {
21+
value: function () {
22+
return Date.now() - _perfNowZeroTime;
23+
}, writable: true, enumerable: false, configurable: true
24+
});
25+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* RegExp.prototype.compile() polyfill, described in E6 Annex B:
3+
*
4+
* https://people.mozilla.org/~jorendorff/es6-draft.html#sec-regexp.prototype.compile
5+
*
6+
* See also:
7+
*
8+
* http://mozilla.6506.n7.nabble.com/RegExp-prototype-compile-and-RegExp-instance-properties-td270408.html
9+
*
10+
* This polyfill cannot be implemented in terms of standard E5 because it
11+
* needs to reinitialize the internal state of a RegExp instance. To do
12+
* that, we access the Duktape internal properties directly, which is
13+
* quite fragile.
14+
*
15+
* Avoid storing a public copy of Duktape or some internal property name in
16+
* the global object. This could subvert user sandboxing.
17+
*/
18+
19+
(function () {
20+
var propBytecode = Duktape.dec('hex', 'ff62797465636f6465'); // \xFFbytecode
21+
22+
if (typeof RegExp.prototype.compile !== 'undefined') {
23+
return;
24+
}
25+
26+
Object.defineProperty(RegExp.prototype, 'compile', {
27+
value: function (pattern, flags) {
28+
var newBytecode, tmpRegexp;
29+
if (typeof this !== 'object' || !(propBytecode in this)) {
30+
throw new TypeError('invalid this binding');
31+
}
32+
33+
// FIXME: property attributes prevent this approach from working
34+
// right now. The properties we'd need to modify are non-writable
35+
// and non-configurable:
36+
//
37+
// \xffbytecode
38+
// source
39+
// global
40+
// ignoreCase
41+
// multiline
42+
//
43+
// The property attributes can be relaxed, or the properties can
44+
// be made accessors backing to the regexp bytecode, see Ditz
45+
// issues: 0f2c246cadbb3b3913b75dc7e890ee4e7d336a1a and
46+
// f8396fbcc36db4610fec5ad5a7d7a8f471d084a4.
47+
48+
if (typeof pattern === 'object' && (propBytecode in pattern)) {
49+
this[propBytecode] = pattern[propBytecode];
50+
} else {
51+
tmpRegexp = new RegExp(pattern, flags);
52+
this[propBytecode] = tmpRegexp[propBytecode];
53+
}
54+
55+
//this.source
56+
//this.global
57+
//this.ignoreCase
58+
//this.multiline
59+
this.lastIndex = 0;
60+
return this;
61+
}, writable: true, enumerable: false, configurable: true
62+
});
63+
64+
throw new Error('RegExp.prototype.compile() polyfill incomplete');
65+
})();

util/make_dist.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ for i in \
188188
console-minimal.js \
189189
object-prototype-definegetter.js \
190190
object-prototype-definesetter.js \
191+
object-assign.js \
192+
performance-now.js \
191193
; do
192194
cp polyfills/$i $DIST/polyfills/
193195
done

0 commit comments

Comments
 (0)