OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 | |
29 // This file relies on the fact that the following declarations have been made | 28 // This file relies on the fact that the following declarations have been made |
30 // | 29 // |
31 // in runtime.js: | 30 // in runtime.js: |
32 // const $Object = global.Object; | 31 // const $Object = global.Object; |
33 // const $Boolean = global.Boolean; | 32 // const $Boolean = global.Boolean; |
34 // const $Number = global.Number; | 33 // const $Number = global.Number; |
35 // const $Function = global.Function; | 34 // const $Function = global.Function; |
36 // const $Array = global.Array; | 35 // const $Array = global.Array; |
37 // const $NaN = 0/0; | 36 // const $NaN = 0/0; |
38 // | 37 // |
39 // in math.js: | 38 // in math.js: |
40 // const $floor = MathFloor | 39 // const $floor = MathFloor |
41 | 40 |
| 41 const $isNaN = GlobalIsNaN; |
| 42 const $isFinite = GlobalIsFinite; |
42 | 43 |
43 // ECMA 262 - 15.1.1.1. | 44 // ---------------------------------------------------------------------------- |
44 %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE); | |
45 | 45 |
46 | 46 |
47 // ECMA-262 - 15.1.1.2. | 47 // Helper function used to install functions on objects. |
48 %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE); | 48 function InstallFunctions(object, attributes, functions) { |
| 49 for (var i = 0; i < functions.length; i += 2) { |
| 50 var key = functions[i]; |
| 51 var f = functions[i + 1]; |
| 52 %FunctionSetName(f, key); |
| 53 %SetProperty(object, key, f, attributes); |
| 54 } |
| 55 } |
49 | 56 |
50 | 57 |
51 // ECMA-262 - 15.1.1.3. | 58 // ---------------------------------------------------------------------------- |
52 %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE); | |
53 | 59 |
54 | 60 |
55 // ECMA 262 - 15.1.4 | 61 // ECMA 262 - 15.1.4 |
56 function $isNaN(number) { | 62 function GlobalIsNaN(number) { |
57 var n = ToNumber(number); | 63 var n = ToNumber(number); |
58 return NUMBER_IS_NAN(n); | 64 return NUMBER_IS_NAN(n); |
59 } | 65 } |
60 %SetProperty(global, "isNaN", $isNaN, DONT_ENUM); | |
61 | 66 |
62 | 67 |
63 // ECMA 262 - 15.1.5 | 68 // ECMA 262 - 15.1.5 |
64 function $isFinite(number) { | 69 function GlobalIsFinite(number) { |
65 return %NumberIsFinite(ToNumber(number)); | 70 return %NumberIsFinite(ToNumber(number)); |
66 } | 71 } |
67 %SetProperty(global, "isFinite", $isFinite, DONT_ENUM); | |
68 | 72 |
69 | 73 |
70 // ECMA-262 - 15.1.2.2 | 74 // ECMA-262 - 15.1.2.2 |
71 %SetProperty(global, "parseInt", function(string, radix) { | 75 function GlobalParseInt(string, radix) { |
72 if (radix === void 0) { | 76 if (radix === void 0) { |
73 radix = 0; | 77 radix = 0; |
74 // Some people use parseInt instead of Math.floor. This | 78 // Some people use parseInt instead of Math.floor. This |
75 // optimization makes parseInt on a Smi 12 times faster (60ns | 79 // optimization makes parseInt on a Smi 12 times faster (60ns |
76 // vs 800ns). The following optimization makes parseInt on a | 80 // vs 800ns). The following optimization makes parseInt on a |
77 // non-Smi number 9 times faster (230ns vs 2070ns). Together | 81 // non-Smi number 9 times faster (230ns vs 2070ns). Together |
78 // they make parseInt on a string 1.4% slower (274ns vs 270ns). | 82 // they make parseInt on a string 1.4% slower (274ns vs 270ns). |
79 if (%_IsSmi(string)) return string; | 83 if (%_IsSmi(string)) return string; |
80 if (IS_NUMBER(string)) { | 84 if (IS_NUMBER(string)) { |
81 if (string >= 0.01 && string < 1e9) | 85 if (string >= 0.01 && string < 1e9) |
82 return $floor(string); | 86 return $floor(string); |
83 if (string <= -0.01 && string > -1e9) | 87 if (string <= -0.01 && string > -1e9) |
84 return - $floor(-string); | 88 return - $floor(-string); |
85 } | 89 } |
86 } else { | 90 } else { |
87 radix = TO_INT32(radix); | 91 radix = TO_INT32(radix); |
88 if (!(radix == 0 || (2 <= radix && radix <= 36))) | 92 if (!(radix == 0 || (2 <= radix && radix <= 36))) |
89 return $NaN; | 93 return $NaN; |
90 } | 94 } |
91 return %StringParseInt(ToString(string), radix); | 95 return %StringParseInt(ToString(string), radix); |
92 }, DONT_ENUM); | 96 } |
93 | 97 |
94 | 98 |
95 // ECMA-262 - 15.1.2.3 | 99 // ECMA-262 - 15.1.2.3 |
96 %SetProperty(global, "parseFloat", function(string) { | 100 function GlobalParseFloat(string) { |
97 return %StringParseFloat(ToString(string)); | 101 return %StringParseFloat(ToString(string)); |
98 }, DONT_ENUM); | 102 } |
| 103 |
| 104 |
| 105 function GlobalEval(x) { |
| 106 if (!IS_STRING(x)) return x; |
| 107 |
| 108 var f = %CompileString(x, 0, true); |
| 109 if (!IS_FUNCTION(f)) return f; |
| 110 |
| 111 return f.call(%EvalReceiver(this)); |
| 112 } |
| 113 |
| 114 |
| 115 // execScript for IE compatibility. |
| 116 function GlobalExecScript(expr, lang) { |
| 117 // NOTE: We don't care about the character casing. |
| 118 if (!lang || /javascript/i.test(lang)) { |
| 119 var f = %CompileString(ToString(expr), 0, false); |
| 120 f.call(global); |
| 121 } |
| 122 return null; |
| 123 } |
| 124 |
| 125 |
| 126 // ---------------------------------------------------------------------------- |
| 127 |
| 128 |
| 129 function SetupGlobal() { |
| 130 // ECMA 262 - 15.1.1.1. |
| 131 %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE); |
| 132 |
| 133 // ECMA-262 - 15.1.1.2. |
| 134 %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE); |
| 135 |
| 136 // ECMA-262 - 15.1.1.3. |
| 137 %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE); |
| 138 |
| 139 // Setup non-enumerable function on the global object. |
| 140 InstallFunctions(global, DONT_ENUM, $Array( |
| 141 "isNaN", GlobalIsNaN, |
| 142 "isFinite", GlobalIsFinite, |
| 143 "parseInt", GlobalParseInt, |
| 144 "parseFloat", GlobalParseFloat, |
| 145 "eval", GlobalEval, |
| 146 "execScript", GlobalExecScript |
| 147 )); |
| 148 } |
| 149 |
| 150 SetupGlobal(); |
99 | 151 |
100 | 152 |
101 // ---------------------------------------------------------------------------- | 153 // ---------------------------------------------------------------------------- |
102 // Boolean (first part of definition) | 154 // Boolean (first part of definition) |
103 | 155 |
104 | 156 |
105 %SetCode($Boolean, function(x) { | 157 %SetCode($Boolean, function(x) { |
106 if (%IsConstructCall()) { | 158 if (%IsConstructCall()) { |
107 %_SetValueOf(this, ToBoolean(x)); | 159 %_SetValueOf(this, ToBoolean(x)); |
108 } else { | 160 } else { |
109 return ToBoolean(x); | 161 return ToBoolean(x); |
110 } | 162 } |
111 }); | 163 }); |
112 | 164 |
113 %FunctionSetPrototype($Boolean, new $Boolean(false)); | 165 %FunctionSetPrototype($Boolean, new $Boolean(false)); |
114 | 166 |
115 %SetProperty($Boolean.prototype, "constructor", $Boolean, DONT_ENUM); | 167 %SetProperty($Boolean.prototype, "constructor", $Boolean, DONT_ENUM); |
116 | 168 |
117 // ---------------------------------------------------------------------------- | 169 // ---------------------------------------------------------------------------- |
118 // Object | 170 // Object |
119 | 171 |
120 $Object.prototype.constructor = $Object; | 172 $Object.prototype.constructor = $Object; |
121 | 173 |
122 %SetProperty($Object.prototype, "toString", function() { | 174 // ECMA-262 - 15.2.4.2 |
| 175 function ObjectToString() { |
123 var c = %ClassOf(this); | 176 var c = %ClassOf(this); |
124 // Hide Arguments from the outside. | 177 // Hide Arguments from the outside. |
125 if (c === 'Arguments') c = 'Object'; | 178 if (c === 'Arguments') c = 'Object'; |
126 return "[object " + c + "]"; | 179 return "[object " + c + "]"; |
127 }, DONT_ENUM); | 180 } |
128 | 181 |
129 | 182 |
130 // ECMA-262, section 15.2.4.3, page 84. | 183 // ECMA-262 - 15.2.4.3 |
131 %SetProperty($Object.prototype, "toLocaleString", function() { | 184 function ObjectToLocaleString() { |
132 return this.toString(); | 185 return this.toString(); |
133 }, DONT_ENUM); | 186 } |
134 | 187 |
135 | 188 |
136 // ECMA-262, section 15.2.4.4, page 85. | 189 // ECMA-262 - 15.2.4.4 |
137 %SetProperty($Object.prototype, "valueOf", function() { | 190 function ObjectValueOf() { |
138 return this; | 191 return this; |
139 }, DONT_ENUM); | 192 } |
140 | 193 |
141 | 194 |
142 // ECMA-262, section 15.2.4.5, page 85. | 195 // ECMA-262 - 15.2.4.5 |
143 %SetProperty($Object.prototype, "hasOwnProperty", function(V) { | 196 function ObjectHasOwnProperty(V) { |
144 return %HasLocalProperty(ToObject(this), ToString(V)); | 197 return %HasLocalProperty(ToObject(this), ToString(V)); |
145 }, DONT_ENUM); | 198 } |
146 | 199 |
147 | 200 |
148 // ECMA-262, section 15.2.4.6, page 85. | 201 // ECMA-262 - 15.2.4.6 |
149 %SetProperty($Object.prototype, "isPrototypeOf", function(V) { | 202 function ObjectIsPrototypeOf(V) { |
150 if (!IS_OBJECT(V) && !IS_FUNCTION(V)) return false; | 203 if (!IS_OBJECT(V) && !IS_FUNCTION(V)) return false; |
151 return %IsInPrototypeChain(this, V); | 204 return %IsInPrototypeChain(this, V); |
152 }, DONT_ENUM); | 205 } |
153 | 206 |
154 | 207 |
155 // ECMA-262, section 15.2.4.6, page 85. | 208 // ECMA-262 - 15.2.4.6 |
156 %SetProperty($Object.prototype, "propertyIsEnumerable", function(V) { | 209 function ObjectPropertyIsEnumerable(V) { |
157 if (this == null) return false; | 210 if (this == null) return false; |
158 if (!IS_OBJECT(this) && !IS_FUNCTION(this)) return false; | 211 if (!IS_OBJECT(this) && !IS_FUNCTION(this)) return false; |
159 return %IsPropertyEnumerable(this, ToString(V)); | 212 return %IsPropertyEnumerable(this, ToString(V)); |
160 }, DONT_ENUM); | 213 } |
161 | 214 |
162 | 215 |
163 // Extensions for providing property getters and setters. | 216 // Extensions for providing property getters and setters. |
164 %SetProperty($Object.prototype, "__defineGetter__", function(name, fun) { | 217 function ObjectDefineGetter(name, fun) { |
165 if (this == null) { | 218 if (this == null) { |
166 throw new $TypeError('Object.prototype.__defineGetter__: this is Null'); | 219 throw new $TypeError('Object.prototype.__defineGetter__: this is Null'); |
167 } | 220 } |
168 if (!IS_FUNCTION(fun)) { | 221 if (!IS_FUNCTION(fun)) { |
169 throw new $TypeError( | 222 throw new $TypeError( |
170 'Object.prototype.__defineGetter__: Expecting function'); | 223 'Object.prototype.__defineGetter__: Expecting function'); |
171 } | 224 } |
172 return %DefineAccessor(ToObject(this), ToString(name), GETTER, fun); | 225 return %DefineAccessor(ToObject(this), ToString(name), GETTER, fun); |
173 }, DONT_ENUM); | 226 } |
174 | 227 |
175 | 228 |
176 | 229 function ObjectLookupGetter(name) { |
177 %SetProperty($Object.prototype, "__lookupGetter__", function(name) { | |
178 if (this == null) { | 230 if (this == null) { |
179 throw new $TypeError('Object.prototype.__lookupGetter__: this is Null'); | 231 throw new $TypeError('Object.prototype.__lookupGetter__: this is Null'); |
180 } | 232 } |
181 return %LookupAccessor(ToObject(this), ToString(name), GETTER); | 233 return %LookupAccessor(ToObject(this), ToString(name), GETTER); |
182 }, DONT_ENUM); | 234 } |
183 | 235 |
184 | 236 |
185 %SetProperty($Object.prototype, "__defineSetter__", function(name, fun) { | 237 function ObjectDefineSetter(name, fun) { |
186 if (this == null) { | 238 if (this == null) { |
187 throw new $TypeError('Object.prototype.__defineSetter__: this is Null'); | 239 throw new $TypeError('Object.prototype.__defineSetter__: this is Null'); |
188 } | 240 } |
189 if (!IS_FUNCTION(fun)) { | 241 if (!IS_FUNCTION(fun)) { |
190 throw new $TypeError( | 242 throw new $TypeError( |
191 'Object.prototype.__defineSetter__: Expecting function'); | 243 'Object.prototype.__defineSetter__: Expecting function'); |
192 } | 244 } |
193 return %DefineAccessor(ToObject(this), ToString(name), SETTER, fun); | 245 return %DefineAccessor(ToObject(this), ToString(name), SETTER, fun); |
194 }, DONT_ENUM); | 246 } |
195 | 247 |
196 | 248 |
197 %SetProperty($Object.prototype, "__lookupSetter__", function(name) { | 249 function ObjectLookupSetter(name) { |
198 if (this == null) { | 250 if (this == null) { |
199 throw new $TypeError('Object.prototype.__lookupSetter__: this is Null'); | 251 throw new $TypeError('Object.prototype.__lookupSetter__: this is Null'); |
200 } | 252 } |
201 return %LookupAccessor(ToObject(this), ToString(name), SETTER); | 253 return %LookupAccessor(ToObject(this), ToString(name), SETTER); |
202 }, DONT_ENUM); | 254 } |
203 | 255 |
204 | 256 |
205 %SetCode($Object, function(x) { | 257 %SetCode($Object, function(x) { |
206 if (%IsConstructCall()) { | 258 if (%IsConstructCall()) { |
207 if (x == null) return this; | 259 if (x == null) return this; |
208 return ToObject(x); | 260 return ToObject(x); |
209 } else { | 261 } else { |
210 if (x == null) return { }; | 262 if (x == null) return { }; |
211 return ToObject(x); | 263 return ToObject(x); |
212 } | 264 } |
213 }); | 265 }); |
214 | 266 |
215 | 267 |
216 // ---------------------------------------------------------------------------- | 268 // ---------------------------------------------------------------------------- |
217 // Global stuff... | |
218 | |
219 %SetProperty(global, "eval", function(x) { | |
220 if (!IS_STRING(x)) return x; | |
221 | |
222 var f = %CompileString(x, 0, true); | |
223 if (!IS_FUNCTION(f)) return f; | |
224 | |
225 return f.call(%EvalReceiver(this)); | |
226 }, DONT_ENUM); | |
227 | 269 |
228 | 270 |
229 // execScript for IE compatibility. | 271 function SetupObject() { |
230 %SetProperty(global, "execScript", function(expr, lang) { | 272 // Setup non-enumerable functions on the Object.prototype object. |
231 // NOTE: We don't care about the character casing. | 273 InstallFunctions($Object.prototype, DONT_ENUM, $Array( |
232 if (!lang || /javascript/i.test(lang)) { | 274 "toString", ObjectToString, |
233 var f = %CompileString(ToString(expr), 0, false); | 275 "toLocaleString", ObjectToLocaleString, |
234 f.call(global); | 276 "valueOf", ObjectValueOf, |
235 } | 277 "hasOwnProperty", ObjectHasOwnProperty, |
236 return null; | 278 "isPrototypeOf", ObjectIsPrototypeOf, |
237 }, DONT_ENUM); | 279 "propertyIsEnumerable", ObjectPropertyIsEnumerable, |
| 280 "__defineGetter__", ObjectDefineGetter, |
| 281 "__lookupGetter__", ObjectLookupGetter, |
| 282 "__defineSetter__", ObjectDefineSetter, |
| 283 "__lookupSetter__", ObjectLookupSetter |
| 284 )); |
| 285 } |
| 286 |
| 287 SetupObject(); |
238 | 288 |
239 | 289 |
240 // ---------------------------------------------------------------------------- | 290 // ---------------------------------------------------------------------------- |
241 // Boolean | 291 // Boolean |
242 | 292 |
243 %SetProperty($Boolean.prototype, "toString", function() { | 293 function BooleanToString() { |
244 // NOTE: Both Boolean objects and values can enter here as | 294 // NOTE: Both Boolean objects and values can enter here as |
245 // 'this'. This is not as dictated by ECMA-262. | 295 // 'this'. This is not as dictated by ECMA-262. |
246 if (!IS_BOOLEAN(this) && %ClassOf(this) !== 'Boolean') | 296 if (!IS_BOOLEAN(this) && %ClassOf(this) !== 'Boolean') |
247 throw new $TypeError('Boolean.prototype.toString is not generic'); | 297 throw new $TypeError('Boolean.prototype.toString is not generic'); |
248 return ToString(%_ValueOf(this)); | 298 return ToString(%_ValueOf(this)); |
249 }, DONT_ENUM); | 299 } |
250 | 300 |
251 | 301 |
252 %SetProperty($Boolean.prototype, "valueOf", function() { | 302 function BooleanValueOf() { |
253 // NOTE: Both Boolean objects and values can enter here as | 303 // NOTE: Both Boolean objects and values can enter here as |
254 // 'this'. This is not as dictated by ECMA-262. | 304 // 'this'. This is not as dictated by ECMA-262. |
255 if (!IS_BOOLEAN(this) && %ClassOf(this) !== 'Boolean') | 305 if (!IS_BOOLEAN(this) && %ClassOf(this) !== 'Boolean') |
256 throw new $TypeError('Boolean.prototype.valueOf is not generic'); | 306 throw new $TypeError('Boolean.prototype.valueOf is not generic'); |
257 return %_ValueOf(this); | 307 return %_ValueOf(this); |
258 }, DONT_ENUM); | 308 } |
259 | 309 |
260 | 310 |
261 // ---------------------------------------------------------------------------- | 311 // ---------------------------------------------------------------------------- |
| 312 |
| 313 |
| 314 function SetupBoolean() { |
| 315 InstallFunctions($Boolean.prototype, DONT_ENUM, $Array( |
| 316 "toString", BooleanToString, |
| 317 "valueOf", BooleanValueOf |
| 318 )); |
| 319 } |
| 320 |
| 321 SetupBoolean(); |
| 322 |
| 323 // ---------------------------------------------------------------------------- |
262 // Number | 324 // Number |
263 | 325 |
264 // Set the Number function and constructor. | 326 // Set the Number function and constructor. |
265 %SetCode($Number, function(x) { | 327 %SetCode($Number, function(x) { |
266 var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x); | 328 var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x); |
267 if (%IsConstructCall()) { | 329 if (%IsConstructCall()) { |
268 %_SetValueOf(this, value); | 330 %_SetValueOf(this, value); |
269 } else { | 331 } else { |
270 return value; | 332 return value; |
271 } | 333 } |
272 }); | 334 }); |
273 | 335 |
274 %FunctionSetPrototype($Number, new $Number(0)); | 336 %FunctionSetPrototype($Number, new $Number(0)); |
275 | 337 |
276 %SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM); | |
277 | |
278 // ECMA-262 section 15.7.3.1. | |
279 %SetProperty($Number, | |
280 "MAX_VALUE", | |
281 1.7976931348623157e+308, | |
282 DONT_ENUM | DONT_DELETE | READ_ONLY); | |
283 | |
284 // ECMA-262 section 15.7.3.2. | |
285 %SetProperty($Number, "MIN_VALUE", 5e-324, DONT_ENUM | DONT_DELETE | READ_ONLY); | |
286 | |
287 // ECMA-262 section 15.7.3.3. | |
288 %SetProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY); | |
289 | |
290 // ECMA-262 section 15.7.3.4. | |
291 %SetProperty($Number, | |
292 "NEGATIVE_INFINITY", | |
293 -1/0, | |
294 DONT_ENUM | DONT_DELETE | READ_ONLY); | |
295 | |
296 // ECMA-262 section 15.7.3.5. | |
297 %SetProperty($Number, | |
298 "POSITIVE_INFINITY", | |
299 1/0, | |
300 DONT_ENUM | DONT_DELETE | READ_ONLY); | |
301 | |
302 // ECMA-262 section 15.7.4.2. | 338 // ECMA-262 section 15.7.4.2. |
303 %SetProperty($Number.prototype, "toString", function(radix) { | 339 function NumberToString(radix) { |
304 // NOTE: Both Number objects and values can enter here as | 340 // NOTE: Both Number objects and values can enter here as |
305 // 'this'. This is not as dictated by ECMA-262. | 341 // 'this'. This is not as dictated by ECMA-262. |
306 var number = this; | 342 var number = this; |
307 if (!IS_NUMBER(this)) { | 343 if (!IS_NUMBER(this)) { |
308 if (%ClassOf(this) !== 'Number') | 344 if (%ClassOf(this) !== 'Number') |
309 throw new $TypeError('Number.prototype.toString is not generic'); | 345 throw new $TypeError('Number.prototype.toString is not generic'); |
310 // Get the value of this number in case it's an object. | 346 // Get the value of this number in case it's an object. |
311 number = %_ValueOf(this); | 347 number = %_ValueOf(this); |
312 } | 348 } |
313 // Fast case: Convert number in radix 10. | 349 // Fast case: Convert number in radix 10. |
314 if (IS_UNDEFINED(radix) || radix === 10) { | 350 if (IS_UNDEFINED(radix) || radix === 10) { |
315 return ToString(number); | 351 return ToString(number); |
316 } | 352 } |
317 | 353 |
318 // Convert the radix to an integer and check the range. | 354 // Convert the radix to an integer and check the range. |
319 radix = TO_INTEGER(radix); | 355 radix = TO_INTEGER(radix); |
320 if (radix < 2 || radix > 36) { | 356 if (radix < 2 || radix > 36) { |
321 throw new $RangeError('toString() radix argument must be between 2 and 36'); | 357 throw new $RangeError('toString() radix argument must be between 2 and 36'); |
322 } | 358 } |
323 // Convert the number to a string in the given radix. | 359 // Convert the number to a string in the given radix. |
324 return %NumberToRadixString(number, radix); | 360 return %NumberToRadixString(number, radix); |
325 }, DONT_ENUM); | 361 } |
326 | 362 |
327 | 363 |
328 // ECMA-262 section 15.7.4.3 | 364 // ECMA-262 section 15.7.4.3 |
329 %SetProperty($Number.prototype, "toLocaleString", function() { | 365 function NumberToLocaleString() { |
330 return this.toString(); | 366 return this.toString(); |
331 }, DONT_ENUM); | 367 } |
332 | 368 |
333 | 369 |
334 // ECMA-262 section 15.7.4.4 | 370 // ECMA-262 section 15.7.4.4 |
335 %SetProperty($Number.prototype, "valueOf", function() { | 371 function NumberValueOf() { |
336 // NOTE: Both Number objects and values can enter here as | 372 // NOTE: Both Number objects and values can enter here as |
337 // 'this'. This is not as dictated by ECMA-262. | 373 // 'this'. This is not as dictated by ECMA-262. |
338 if (!IS_NUMBER(this) && %ClassOf(this) !== 'Number') | 374 if (!IS_NUMBER(this) && %ClassOf(this) !== 'Number') |
339 throw new $TypeError('Number.prototype.valueOf is not generic'); | 375 throw new $TypeError('Number.prototype.valueOf is not generic'); |
340 return %_ValueOf(this); | 376 return %_ValueOf(this); |
341 }, DONT_ENUM); | 377 } |
342 | 378 |
343 | 379 |
344 // ECMA-262 section 15.7.4.5 | 380 // ECMA-262 section 15.7.4.5 |
345 %SetProperty($Number.prototype, "toFixed", function(fractionDigits) { | 381 function NumberToFixed(fractionDigits) { |
346 var f = TO_INTEGER(fractionDigits); | 382 var f = TO_INTEGER(fractionDigits); |
347 if (f < 0 || f > 20) { | 383 if (f < 0 || f > 20) { |
348 throw new $RangeError("toFixed() digits argument must be between 0 and 20"); | 384 throw new $RangeError("toFixed() digits argument must be between 0 and 20"); |
349 } | 385 } |
350 var x = ToNumber(this); | 386 var x = ToNumber(this); |
351 return %NumberToFixed(x, f); | 387 return %NumberToFixed(x, f); |
352 }, DONT_ENUM); | 388 } |
353 | 389 |
354 | 390 |
355 // ECMA-262 section 15.7.4.6 | 391 // ECMA-262 section 15.7.4.6 |
356 %SetProperty($Number.prototype, "toExponential", function(fractionDigits) { | 392 function NumberToExponential(fractionDigits) { |
357 var f = -1; | 393 var f = -1; |
358 if (!IS_UNDEFINED(fractionDigits)) { | 394 if (!IS_UNDEFINED(fractionDigits)) { |
359 f = TO_INTEGER(fractionDigits); | 395 f = TO_INTEGER(fractionDigits); |
360 if (f < 0 || f > 20) { | 396 if (f < 0 || f > 20) { |
361 throw new $RangeError("toExponential() argument must be between 0 and 20")
; | 397 throw new $RangeError("toExponential() argument must be between 0 and 20")
; |
362 } | 398 } |
363 } | 399 } |
364 var x = ToNumber(this); | 400 var x = ToNumber(this); |
365 return %NumberToExponential(x, f); | 401 return %NumberToExponential(x, f); |
366 }, DONT_ENUM); | 402 } |
367 | 403 |
368 | 404 |
369 // ECMA-262 section 15.7.4.7 | 405 // ECMA-262 section 15.7.4.7 |
370 %SetProperty($Number.prototype, "toPrecision", function(precision) { | 406 function NumberToPrecision(precision) { |
371 if (IS_UNDEFINED(precision)) return ToString(%_ValueOf(this)); | 407 if (IS_UNDEFINED(precision)) return ToString(%_ValueOf(this)); |
372 var p = TO_INTEGER(precision); | 408 var p = TO_INTEGER(precision); |
373 if (p < 1 || p > 21) { | 409 if (p < 1 || p > 21) { |
374 throw new $RangeError("toPrecision() argument must be between 1 and 21"); | 410 throw new $RangeError("toPrecision() argument must be between 1 and 21"); |
375 } | 411 } |
376 var x = ToNumber(this); | 412 var x = ToNumber(this); |
377 return %NumberToPrecision(x, p); | 413 return %NumberToPrecision(x, p); |
378 }, DONT_ENUM); | 414 } |
| 415 |
| 416 |
| 417 // ---------------------------------------------------------------------------- |
| 418 |
| 419 function SetupNumber() { |
| 420 // Setup the constructor property on the Number prototype object. |
| 421 %SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM); |
| 422 |
| 423 // ECMA-262 section 15.7.3.1. |
| 424 %SetProperty($Number, |
| 425 "MAX_VALUE", |
| 426 1.7976931348623157e+308, |
| 427 DONT_ENUM | DONT_DELETE | READ_ONLY); |
| 428 |
| 429 // ECMA-262 section 15.7.3.2. |
| 430 %SetProperty($Number, "MIN_VALUE", 5e-324, DONT_ENUM | DONT_DELETE | READ_ONLY
); |
| 431 |
| 432 // ECMA-262 section 15.7.3.3. |
| 433 %SetProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY); |
| 434 |
| 435 // ECMA-262 section 15.7.3.4. |
| 436 %SetProperty($Number, |
| 437 "NEGATIVE_INFINITY", |
| 438 -1/0, |
| 439 DONT_ENUM | DONT_DELETE | READ_ONLY); |
| 440 |
| 441 // ECMA-262 section 15.7.3.5. |
| 442 %SetProperty($Number, |
| 443 "POSITIVE_INFINITY", |
| 444 1/0, |
| 445 DONT_ENUM | DONT_DELETE | READ_ONLY); |
| 446 |
| 447 // Setup non-enumerable functions on the Number prototype object. |
| 448 InstallFunctions($Number.prototype, DONT_ENUM, $Array( |
| 449 "toString", NumberToString, |
| 450 "toLocaleString", NumberToLocaleString, |
| 451 "valueOf", NumberValueOf, |
| 452 "toFixed", NumberToFixed, |
| 453 "toExponential", NumberToExponential, |
| 454 "toPrecision", NumberToPrecision |
| 455 )); |
| 456 } |
| 457 |
| 458 SetupNumber(); |
| 459 |
379 | 460 |
380 | 461 |
381 // ---------------------------------------------------------------------------- | 462 // ---------------------------------------------------------------------------- |
382 // Function | 463 // Function |
383 | 464 |
384 $Function.prototype.constructor = $Function; | 465 $Function.prototype.constructor = $Function; |
385 | 466 |
386 | |
387 function FunctionSourceString(func) { | 467 function FunctionSourceString(func) { |
388 // NOTE: Both Function objects and values can enter here as | 468 // NOTE: Both Function objects and values can enter here as |
389 // 'func'. This is not as dictated by ECMA-262. | 469 // 'func'. This is not as dictated by ECMA-262. |
390 if (!IS_FUNCTION(func) && %ClassOf(func) != 'Function') | 470 if (!IS_FUNCTION(func) && %ClassOf(func) != 'Function') |
391 throw new $TypeError('Function.prototype.toString is not generic'); | 471 throw new $TypeError('Function.prototype.toString is not generic'); |
392 | 472 |
393 var source = %FunctionGetSourceCode(func); | 473 var source = %FunctionGetSourceCode(func); |
394 if (!IS_STRING(source)) { | 474 if (!IS_STRING(source)) { |
395 var name = %FunctionGetName(func); | 475 var name = %FunctionGetName(func); |
396 if (name) { | 476 if (name) { |
397 // Mimic what KJS does. | 477 // Mimic what KJS does. |
398 return 'function ' + name + '() { [native code] }'; | 478 return 'function ' + name + '() { [native code] }'; |
399 } else { | 479 } else { |
400 return 'function () { [native code] }'; | 480 return 'function () { [native code] }'; |
401 } | 481 } |
402 } | 482 } |
403 | 483 |
404 // Censor occurrences of internal calls. We do that for all | 484 // Censor occurrences of internal calls. We do that for all |
405 // functions and don't cache under the assumption that people rarly | 485 // functions and don't cache under the assumption that people rarly |
406 // convert functions to strings. Note that we (apparently) can't | 486 // convert functions to strings. Note that we (apparently) can't |
407 // use regular expression literals in natives files. | 487 // use regular expression literals in natives files. |
408 var regexp = ORIGINAL_REGEXP("%(\\w+\\()", "gm"); | 488 var regexp = ORIGINAL_REGEXP("%(\\w+\\()", "gm"); |
409 if (source.match(regexp)) source = source.replace(regexp, "$1"); | 489 if (source.match(regexp)) source = source.replace(regexp, "$1"); |
410 var name = %FunctionGetName(func); | 490 var name = %FunctionGetName(func); |
411 return 'function ' + name + source; | 491 return 'function ' + name + source; |
412 } | 492 } |
413 | 493 |
414 | 494 |
415 %SetProperty($Function.prototype, "toString", function() { | 495 function FunctionToString() { |
416 return FunctionSourceString(this); | 496 return FunctionSourceString(this); |
417 }, DONT_ENUM); | 497 } |
418 | 498 |
419 | 499 |
420 function NewFunction(arg1) { // length == 1 | 500 function NewFunction(arg1) { // length == 1 |
421 var n = %_ArgumentsLength(); | 501 var n = %_ArgumentsLength(); |
422 var p = ''; | 502 var p = ''; |
423 if (n > 1) { | 503 if (n > 1) { |
424 p = new $Array(n - 1); | 504 p = new $Array(n - 1); |
425 // Explicitly convert all parameters to strings. | 505 // Explicitly convert all parameters to strings. |
426 // Array.prototype.join replaces null with empty strings which is | 506 // Array.prototype.join replaces null with empty strings which is |
427 // not appropriate. | 507 // not appropriate. |
428 for (var i = 0; i < n - 1; i++) p[i] = ToString(%_Arguments(i)); | 508 for (var i = 0; i < n - 1; i++) p[i] = ToString(%_Arguments(i)); |
429 p = p.join(','); | 509 p = p.join(','); |
430 // If the formal parameters string include ) - an illegal | 510 // If the formal parameters string include ) - an illegal |
431 // character - it may make the combined function expression | 511 // character - it may make the combined function expression |
432 // compile. We avoid this problem by checking for this early on. | 512 // compile. We avoid this problem by checking for this early on. |
433 if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]); | 513 if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]); |
434 } | 514 } |
435 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : ''; | 515 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : ''; |
436 var source = '(function(' + p + ') {\n' + body + '\n})'; | 516 var source = '(function(' + p + ') {\n' + body + '\n})'; |
437 | 517 |
438 // The call to SetNewFunctionAttributes will ensure the prototype | 518 // The call to SetNewFunctionAttributes will ensure the prototype |
439 // property of the resulting function is enumerable (ECMA262, 15.3.5.2). | 519 // property of the resulting function is enumerable (ECMA262, 15.3.5.2). |
440 var f = %CompileString(source, -1, false)(); | 520 var f = %CompileString(source, -1, false)(); |
441 %FunctionSetName(f, "anonymous"); | 521 %FunctionSetName(f, "anonymous"); |
442 return %SetNewFunctionAttributes(f); | 522 return %SetNewFunctionAttributes(f); |
443 } | 523 } |
444 | 524 |
445 %SetCode($Function, NewFunction); | 525 %SetCode($Function, NewFunction); |
| 526 |
| 527 // ---------------------------------------------------------------------------- |
| 528 |
| 529 function SetupFunction() { |
| 530 InstallFunctions($Function.prototype, DONT_ENUM, $Array( |
| 531 "toString", FunctionToString |
| 532 )); |
| 533 } |
| 534 |
| 535 SetupFunction(); |
| 536 |
OLD | NEW |