blob: be92347768a71867c546785641dff8b6718ceb60 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000028// This file relies on the fact that the following declarations have been made
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000029//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000030// in runtime.js:
31// const $Object = global.Object;
32// const $Boolean = global.Boolean;
33// const $Number = global.Number;
34// const $Function = global.Function;
35// const $Array = global.Array;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000036// const $NaN = 0/0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000037//
38// in math.js:
39// const $floor = MathFloor
40
41const $isNaN = GlobalIsNaN;
42const $isFinite = GlobalIsFinite;
43
44// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
46
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000047// Helper function used to install functions on objects.
48function InstallFunctions(object, attributes, functions) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000049 if (functions.length >= 8) {
50 %OptimizeObjectForAddingMultipleProperties(object, functions.length >> 1);
51 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000052 for (var i = 0; i < functions.length; i += 2) {
53 var key = functions[i];
54 var f = functions[i + 1];
55 %FunctionSetName(f, key);
56 %SetProperty(object, key, f, attributes);
57 }
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000058 %TransformToFastProperties(object);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000059}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000060
ager@chromium.org9085a012009-05-11 19:22:57 +000061// Emulates JSC by installing functions on a hidden prototype that
62// lies above the current object/prototype. This lets you override
63// functions on String.prototype etc. and then restore the old function
64// with delete. See http://code.google.com/p/chromium/issues/detail?id=1717
65function InstallFunctionsOnHiddenPrototype(object, attributes, functions) {
66 var hidden_prototype = new $Object();
67 %SetHiddenPrototype(object, hidden_prototype);
68 InstallFunctions(hidden_prototype, attributes, functions);
69}
70
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000071
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000072// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000073
74
75// ECMA 262 - 15.1.4
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000076function GlobalIsNaN(number) {
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +000077 var n = ToNumber(number);
78 return NUMBER_IS_NAN(n);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000079}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080
81
82// ECMA 262 - 15.1.5
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000083function GlobalIsFinite(number) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000084 return %NumberIsFinite(ToNumber(number));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000085}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000086
87
88// ECMA-262 - 15.1.2.2
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000089function GlobalParseInt(string, radix) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000090 if (radix === void 0) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000091 // Some people use parseInt instead of Math.floor. This
92 // optimization makes parseInt on a Smi 12 times faster (60ns
93 // vs 800ns). The following optimization makes parseInt on a
94 // non-Smi number 9 times faster (230ns vs 2070ns). Together
95 // they make parseInt on a string 1.4% slower (274ns vs 270ns).
96 if (%_IsSmi(string)) return string;
ager@chromium.org381abbb2009-02-25 13:23:22 +000097 if (IS_NUMBER(string) &&
98 ((string < -0.01 && -1e9 < string) ||
99 (0.01 < string && string < 1e9))) {
100 // Truncate number.
101 return string | 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000102 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000103 radix = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000104 } else {
105 radix = TO_INT32(radix);
106 if (!(radix == 0 || (2 <= radix && radix <= 36)))
107 return $NaN;
108 }
109 return %StringParseInt(ToString(string), radix);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000110}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000111
112
113// ECMA-262 - 15.1.2.3
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000114function GlobalParseFloat(string) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000115 return %StringParseFloat(ToString(string));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000116}
117
118
119function GlobalEval(x) {
120 if (!IS_STRING(x)) return x;
121
ager@chromium.orge2902be2009-06-08 12:21:35 +0000122 var global_receiver = %GlobalReceiver(global);
123 var this_is_global_receiver = (this === global_receiver);
124 var global_is_detached = (global === global_receiver);
125
126 if (!this_is_global_receiver || global_is_detached) {
127 throw new $EvalError('The "this" object passed to eval must ' +
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000128 'be the global object from which eval originated');
129 }
ager@chromium.orge2902be2009-06-08 12:21:35 +0000130
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000131 var f = %CompileString(x, false);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000132 if (!IS_FUNCTION(f)) return f;
133
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000134 return f.call(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000135}
136
137
138// execScript for IE compatibility.
139function GlobalExecScript(expr, lang) {
140 // NOTE: We don't care about the character casing.
141 if (!lang || /javascript/i.test(lang)) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000142 var f = %CompileString(ToString(expr), false);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000143 f.call(%GlobalReceiver(global));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000144 }
145 return null;
146}
147
148
149// ----------------------------------------------------------------------------
150
151
152function SetupGlobal() {
153 // ECMA 262 - 15.1.1.1.
154 %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
155
156 // ECMA-262 - 15.1.1.2.
157 %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE);
158
159 // ECMA-262 - 15.1.1.3.
160 %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000161
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000162 // Setup non-enumerable function on the global object.
163 InstallFunctions(global, DONT_ENUM, $Array(
164 "isNaN", GlobalIsNaN,
165 "isFinite", GlobalIsFinite,
166 "parseInt", GlobalParseInt,
167 "parseFloat", GlobalParseFloat,
168 "eval", GlobalEval,
169 "execScript", GlobalExecScript
170 ));
171}
172
173SetupGlobal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174
175
176// ----------------------------------------------------------------------------
177// Boolean (first part of definition)
178
179
180%SetCode($Boolean, function(x) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000181 if (%_IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182 %_SetValueOf(this, ToBoolean(x));
183 } else {
184 return ToBoolean(x);
185 }
186});
187
188%FunctionSetPrototype($Boolean, new $Boolean(false));
189
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000190%SetProperty($Boolean.prototype, "constructor", $Boolean, DONT_ENUM);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000191
192// ----------------------------------------------------------------------------
193// Object
194
195$Object.prototype.constructor = $Object;
196
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000197// ECMA-262 - 15.2.4.2
198function ObjectToString() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000199 var c = %_ClassOf(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200 // Hide Arguments from the outside.
201 if (c === 'Arguments') c = 'Object';
202 return "[object " + c + "]";
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000203}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000204
205
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000206// ECMA-262 - 15.2.4.3
207function ObjectToLocaleString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000208 return this.toString();
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000209}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210
211
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000212// ECMA-262 - 15.2.4.4
213function ObjectValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214 return this;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000215}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216
217
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000218// ECMA-262 - 15.2.4.5
219function ObjectHasOwnProperty(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220 return %HasLocalProperty(ToObject(this), ToString(V));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000221}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222
223
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000224// ECMA-262 - 15.2.4.6
225function ObjectIsPrototypeOf(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000226 if (!IS_OBJECT(V) && !IS_FUNCTION(V)) return false;
227 return %IsInPrototypeChain(this, V);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000228}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229
230
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000231// ECMA-262 - 15.2.4.6
232function ObjectPropertyIsEnumerable(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000233 if (this == null) return false;
234 if (!IS_OBJECT(this) && !IS_FUNCTION(this)) return false;
235 return %IsPropertyEnumerable(this, ToString(V));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000236}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000237
238
239// Extensions for providing property getters and setters.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000240function ObjectDefineGetter(name, fun) {
241 if (this == null) {
242 throw new $TypeError('Object.prototype.__defineGetter__: this is Null');
243 }
244 if (!IS_FUNCTION(fun)) {
245 throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
246 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000247 return %DefineAccessor(ToObject(this), ToString(name), GETTER, fun);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000248}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249
250
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000251function ObjectLookupGetter(name) {
252 if (this == null) {
253 throw new $TypeError('Object.prototype.__lookupGetter__: this is Null');
254 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000255 return %LookupAccessor(ToObject(this), ToString(name), GETTER);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000256}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000257
258
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000259function ObjectDefineSetter(name, fun) {
260 if (this == null) {
261 throw new $TypeError('Object.prototype.__defineSetter__: this is Null');
262 }
263 if (!IS_FUNCTION(fun)) {
264 throw new $TypeError(
265 'Object.prototype.__defineSetter__: Expecting function');
266 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000267 return %DefineAccessor(ToObject(this), ToString(name), SETTER, fun);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000268}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000269
270
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000271function ObjectLookupSetter(name) {
272 if (this == null) {
273 throw new $TypeError('Object.prototype.__lookupSetter__: this is Null');
274 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000275 return %LookupAccessor(ToObject(this), ToString(name), SETTER);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000276}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000277
278
279%SetCode($Object, function(x) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000280 if (%_IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000281 if (x == null) return this;
282 return ToObject(x);
283 } else {
284 if (x == null) return { };
285 return ToObject(x);
286 }
287});
288
289
290// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000291
292
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000293function SetupObject() {
294 // Setup non-enumerable functions on the Object.prototype object.
295 InstallFunctions($Object.prototype, DONT_ENUM, $Array(
296 "toString", ObjectToString,
297 "toLocaleString", ObjectToLocaleString,
298 "valueOf", ObjectValueOf,
299 "hasOwnProperty", ObjectHasOwnProperty,
300 "isPrototypeOf", ObjectIsPrototypeOf,
301 "propertyIsEnumerable", ObjectPropertyIsEnumerable,
302 "__defineGetter__", ObjectDefineGetter,
303 "__lookupGetter__", ObjectLookupGetter,
304 "__defineSetter__", ObjectDefineSetter,
305 "__lookupSetter__", ObjectLookupSetter
306 ));
307}
308
309SetupObject();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000310
311
312// ----------------------------------------------------------------------------
313// Boolean
314
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000315function BooleanToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000316 // NOTE: Both Boolean objects and values can enter here as
317 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000318 if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000319 throw new $TypeError('Boolean.prototype.toString is not generic');
320 return ToString(%_ValueOf(this));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000321}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000322
323
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000324function BooleanValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000325 // NOTE: Both Boolean objects and values can enter here as
326 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000327 if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000328 throw new $TypeError('Boolean.prototype.valueOf is not generic');
329 return %_ValueOf(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000330}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000331
332
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000333function BooleanToJSON(key) {
334 return CheckJSONPrimitive(this.valueOf());
335}
336
337
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000338// ----------------------------------------------------------------------------
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000339
340
341function SetupBoolean() {
342 InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
343 "toString", BooleanToString,
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000344 "valueOf", BooleanValueOf,
345 "toJSON", BooleanToJSON
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000346 ));
347}
348
349SetupBoolean();
350
351// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000352// Number
353
354// Set the Number function and constructor.
355%SetCode($Number, function(x) {
356 var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000357 if (%_IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000358 %_SetValueOf(this, value);
359 } else {
360 return value;
361 }
362});
363
364%FunctionSetPrototype($Number, new $Number(0));
365
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000366// ECMA-262 section 15.7.4.2.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000367function NumberToString(radix) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368 // NOTE: Both Number objects and values can enter here as
369 // 'this'. This is not as dictated by ECMA-262.
370 var number = this;
371 if (!IS_NUMBER(this)) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000372 if (!IS_NUMBER_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000373 throw new $TypeError('Number.prototype.toString is not generic');
374 // Get the value of this number in case it's an object.
375 number = %_ValueOf(this);
376 }
377 // Fast case: Convert number in radix 10.
378 if (IS_UNDEFINED(radix) || radix === 10) {
379 return ToString(number);
380 }
381
382 // Convert the radix to an integer and check the range.
383 radix = TO_INTEGER(radix);
384 if (radix < 2 || radix > 36) {
385 throw new $RangeError('toString() radix argument must be between 2 and 36');
386 }
387 // Convert the number to a string in the given radix.
388 return %NumberToRadixString(number, radix);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000389}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000390
391
392// ECMA-262 section 15.7.4.3
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000393function NumberToLocaleString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000394 return this.toString();
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000395}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000396
397
398// ECMA-262 section 15.7.4.4
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000399function NumberValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000400 // NOTE: Both Number objects and values can enter here as
401 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000402 if (!IS_NUMBER(this) && !IS_NUMBER_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000403 throw new $TypeError('Number.prototype.valueOf is not generic');
404 return %_ValueOf(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000405}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000406
407
408// ECMA-262 section 15.7.4.5
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000409function NumberToFixed(fractionDigits) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410 var f = TO_INTEGER(fractionDigits);
411 if (f < 0 || f > 20) {
412 throw new $RangeError("toFixed() digits argument must be between 0 and 20");
413 }
414 var x = ToNumber(this);
415 return %NumberToFixed(x, f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000416}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000417
418
419// ECMA-262 section 15.7.4.6
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000420function NumberToExponential(fractionDigits) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000421 var f = -1;
422 if (!IS_UNDEFINED(fractionDigits)) {
423 f = TO_INTEGER(fractionDigits);
424 if (f < 0 || f > 20) {
425 throw new $RangeError("toExponential() argument must be between 0 and 20");
426 }
427 }
428 var x = ToNumber(this);
429 return %NumberToExponential(x, f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000430}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000431
432
433// ECMA-262 section 15.7.4.7
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000434function NumberToPrecision(precision) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000435 if (IS_UNDEFINED(precision)) return ToString(%_ValueOf(this));
436 var p = TO_INTEGER(precision);
437 if (p < 1 || p > 21) {
438 throw new $RangeError("toPrecision() argument must be between 1 and 21");
439 }
440 var x = ToNumber(this);
441 return %NumberToPrecision(x, p);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000442}
443
444
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000445function CheckJSONPrimitive(val) {
446 if (!IsPrimitive(val))
447 throw MakeTypeError('result_not_primitive', ['toJSON', val]);
448 return val;
449}
450
451
452function NumberToJSON(key) {
453 return CheckJSONPrimitive(this.valueOf());
454}
455
456
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000457// ----------------------------------------------------------------------------
458
459function SetupNumber() {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000460 %OptimizeObjectForAddingMultipleProperties($Number.prototype, 8);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000461 // Setup the constructor property on the Number prototype object.
462 %SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
463
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000464 %OptimizeObjectForAddingMultipleProperties($Number, 5);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000465 // ECMA-262 section 15.7.3.1.
466 %SetProperty($Number,
467 "MAX_VALUE",
468 1.7976931348623157e+308,
469 DONT_ENUM | DONT_DELETE | READ_ONLY);
470
471 // ECMA-262 section 15.7.3.2.
472 %SetProperty($Number, "MIN_VALUE", 5e-324, DONT_ENUM | DONT_DELETE | READ_ONLY);
473
474 // ECMA-262 section 15.7.3.3.
475 %SetProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
476
477 // ECMA-262 section 15.7.3.4.
478 %SetProperty($Number,
479 "NEGATIVE_INFINITY",
480 -1/0,
481 DONT_ENUM | DONT_DELETE | READ_ONLY);
482
483 // ECMA-262 section 15.7.3.5.
484 %SetProperty($Number,
485 "POSITIVE_INFINITY",
486 1/0,
487 DONT_ENUM | DONT_DELETE | READ_ONLY);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000488 %TransformToFastProperties($Number);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000489
490 // Setup non-enumerable functions on the Number prototype object.
491 InstallFunctions($Number.prototype, DONT_ENUM, $Array(
492 "toString", NumberToString,
493 "toLocaleString", NumberToLocaleString,
494 "valueOf", NumberValueOf,
495 "toFixed", NumberToFixed,
496 "toExponential", NumberToExponential,
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000497 "toPrecision", NumberToPrecision,
498 "toJSON", NumberToJSON
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000499 ));
500}
501
502SetupNumber();
503
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504
505
506// ----------------------------------------------------------------------------
507// Function
508
509$Function.prototype.constructor = $Function;
510
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000511function FunctionSourceString(func) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000512 if (!IS_FUNCTION(func)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000513 throw new $TypeError('Function.prototype.toString is not generic');
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000514 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515
516 var source = %FunctionGetSourceCode(func);
517 if (!IS_STRING(source)) {
518 var name = %FunctionGetName(func);
519 if (name) {
520 // Mimic what KJS does.
521 return 'function ' + name + '() { [native code] }';
522 } else {
523 return 'function () { [native code] }';
524 }
525 }
526
527 // Censor occurrences of internal calls. We do that for all
528 // functions and don't cache under the assumption that people rarly
529 // convert functions to strings. Note that we (apparently) can't
530 // use regular expression literals in natives files.
531 var regexp = ORIGINAL_REGEXP("%(\\w+\\()", "gm");
532 if (source.match(regexp)) source = source.replace(regexp, "$1");
533 var name = %FunctionGetName(func);
534 return 'function ' + name + source;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000535}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000536
537
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000538function FunctionToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000539 return FunctionSourceString(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000540}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000541
542
543function NewFunction(arg1) { // length == 1
544 var n = %_ArgumentsLength();
545 var p = '';
546 if (n > 1) {
547 p = new $Array(n - 1);
548 // Explicitly convert all parameters to strings.
549 // Array.prototype.join replaces null with empty strings which is
550 // not appropriate.
551 for (var i = 0; i < n - 1; i++) p[i] = ToString(%_Arguments(i));
552 p = p.join(',');
553 // If the formal parameters string include ) - an illegal
554 // character - it may make the combined function expression
555 // compile. We avoid this problem by checking for this early on.
556 if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]);
557 }
558 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : '';
ager@chromium.org236ad962008-09-25 09:45:57 +0000559 var source = '(function(' + p + ') {\n' + body + '\n})';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000560
561 // The call to SetNewFunctionAttributes will ensure the prototype
562 // property of the resulting function is enumerable (ECMA262, 15.3.5.2).
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000563 var f = %CompileString(source, false)();
ager@chromium.org236ad962008-09-25 09:45:57 +0000564 %FunctionSetName(f, "anonymous");
565 return %SetNewFunctionAttributes(f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000566}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000567
568%SetCode($Function, NewFunction);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000569
570// ----------------------------------------------------------------------------
571
572function SetupFunction() {
573 InstallFunctions($Function.prototype, DONT_ENUM, $Array(
574 "toString", FunctionToString
575 ));
576}
577
578SetupFunction();