-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathextensions.js
106 lines (98 loc) · 3.59 KB
/
extensions.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Some extensions to javascript to make the browser environment
// better match the Simplified JavaScript 'native' environment.
Object.newUint8Array = function(size) {
return new Uint8Array(size);
};
// minimal replacement for (new Date()).getTime()
var now = function() {
return (new Date()).getTime();
};
// This replaces the 'new' operator.
Function.prototype.New = function(arg1, arg2) {
// speed optimizations.
if (arguments.length===0) { return new this(); }
if (arguments.length===1) { return new this(arg1); }
if (arguments.length===2) { return new this(arg1, arg2); }
// fully-general implementation.
var object, result;
if (typeof(this.prototype)==="object") {
object = Object.create(this.prototype);
} else {
object = {};
}
result = this.apply(object, arguments);
if (typeof(result)==="object") {
return result;
}
return object;
};
// some special constructors behave differently
RegExp.New = function(re, flags) { return new RegExp(re, flags); };
Function.New = function(args, source) { return new Function(args, source); };
// This replaces the 'instanceof' operator.
Function.prototype.hasInstance = function(obj) {
// a proper definition of this can be written in simplified JS, but
// it requires a bit of special code in the implementation of
// Function.bind.
return obj instanceof this;
};
// provide the delete operator without introducing new syntax
Object['Delete'] = function(o, f) {
delete o[f];
};
// provide exception functionality without introducing new syntax
Object['Throw'] = function(obj) {
throw obj;
};
// XXX: doesn't handle non-local control flow (ie, return from containing
// subroutine inside a bodyBlock)
Object['Try'] = function(_this_, bodyBlock, catchBlock, finallyBlock) {
try {
return bodyBlock.call(_this_);
} catch(e) {
if (catchBlock) catchBlock.call(_this_, e);
else throw e;
} finally {
if (finallyBlock) finallyBlock.call(_this_);
}
};
/*
// Primitive operations, rephrased as message dispatch
Object.prototype['+'] = function(operand) { return this + operand; };
Object.prototype['-'] = function(operand) { return this - operand; };
Object.prototype['*'] = function(operand) { return this * operand; };
Object.prototype['/'] = function(operand) { return this / operand; };
Object.prototype['='] = function(operand) { return this === operand; };
Object.prototype['>'] = function(operand) { return this > operand; };
Object.prototype['>='] = function(operand) { return this >= operand; };
// workarounds for implicit conversions done during dispatch
Number.prototype['='] = function(operand) {
return Number(this) === operand;
};
Boolean.prototype['='] = function(operand) {
return this == operand;
};
String.prototype['='] = function(operand) {
return String(this) === operand;
};
*/
// support for loopless bytecode
Boolean.prototype["while"] = function(_this_, cond, body) {
// strange: === gives the wrong value. == works, because (i think)
// it coerces to string, like the below. ! also does the wrong
// thing. Hm!
if (this.toString() === "false") { return; }
body.call(_this_);
Boolean(cond.call(_this_))["while"](_this_, cond, body);
};
Boolean.prototype["ifElse"] = function(_this_, ifTrue, ifFalse) {
if (this.toString() === "false") {
return ifFalse.call(_this_);
} else {
return ifTrue.call(_this_);
}
};
// it's more natural to write while loops like this:
Function.prototype["while"] = function(_this_, cond) {
Boolean(cond.call(_this_))["while"](_this_, cond, this);
};