blob: 2fecee80c0aebf728a95e88460b335d169e4041d [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
christian.plesner.hansen@gmail.com2bc58ef2009-09-22 10:00:30 +0000279function ObjectKeys(obj) {
280 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
281 throw MakeTypeError('object_keys_non_object', [obj]);
282 return %LocalKeys(obj);
283}
284
285
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000286%SetCode($Object, function(x) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000287 if (%_IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000288 if (x == null) return this;
289 return ToObject(x);
290 } else {
291 if (x == null) return { };
292 return ToObject(x);
293 }
294});
295
296
297// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000298
299
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000300function SetupObject() {
301 // Setup non-enumerable functions on the Object.prototype object.
302 InstallFunctions($Object.prototype, DONT_ENUM, $Array(
303 "toString", ObjectToString,
304 "toLocaleString", ObjectToLocaleString,
305 "valueOf", ObjectValueOf,
306 "hasOwnProperty", ObjectHasOwnProperty,
307 "isPrototypeOf", ObjectIsPrototypeOf,
308 "propertyIsEnumerable", ObjectPropertyIsEnumerable,
309 "__defineGetter__", ObjectDefineGetter,
310 "__lookupGetter__", ObjectLookupGetter,
311 "__defineSetter__", ObjectDefineSetter,
312 "__lookupSetter__", ObjectLookupSetter
313 ));
christian.plesner.hansen@gmail.com2bc58ef2009-09-22 10:00:30 +0000314 InstallFunctions($Object, DONT_ENUM, $Array(
315 "keys", ObjectKeys
316 ));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000317}
318
319SetupObject();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320
321
322// ----------------------------------------------------------------------------
323// Boolean
324
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000325function BooleanToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000326 // NOTE: Both Boolean objects and values can enter here as
327 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000328 if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000329 throw new $TypeError('Boolean.prototype.toString is not generic');
330 return ToString(%_ValueOf(this));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000331}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000332
333
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000334function BooleanValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000335 // NOTE: Both Boolean objects and values can enter here as
336 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000337 if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000338 throw new $TypeError('Boolean.prototype.valueOf is not generic');
339 return %_ValueOf(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000340}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000341
342
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000343function BooleanToJSON(key) {
344 return CheckJSONPrimitive(this.valueOf());
345}
346
347
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000348// ----------------------------------------------------------------------------
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000349
350
351function SetupBoolean() {
352 InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
353 "toString", BooleanToString,
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000354 "valueOf", BooleanValueOf,
355 "toJSON", BooleanToJSON
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000356 ));
357}
358
359SetupBoolean();
360
361// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000362// Number
363
364// Set the Number function and constructor.
365%SetCode($Number, function(x) {
366 var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000367 if (%_IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368 %_SetValueOf(this, value);
369 } else {
370 return value;
371 }
372});
373
374%FunctionSetPrototype($Number, new $Number(0));
375
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000376// ECMA-262 section 15.7.4.2.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000377function NumberToString(radix) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000378 // NOTE: Both Number objects and values can enter here as
379 // 'this'. This is not as dictated by ECMA-262.
380 var number = this;
381 if (!IS_NUMBER(this)) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000382 if (!IS_NUMBER_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000383 throw new $TypeError('Number.prototype.toString is not generic');
384 // Get the value of this number in case it's an object.
385 number = %_ValueOf(this);
386 }
387 // Fast case: Convert number in radix 10.
388 if (IS_UNDEFINED(radix) || radix === 10) {
389 return ToString(number);
390 }
391
392 // Convert the radix to an integer and check the range.
393 radix = TO_INTEGER(radix);
394 if (radix < 2 || radix > 36) {
395 throw new $RangeError('toString() radix argument must be between 2 and 36');
396 }
397 // Convert the number to a string in the given radix.
398 return %NumberToRadixString(number, radix);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000399}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000400
401
402// ECMA-262 section 15.7.4.3
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000403function NumberToLocaleString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404 return this.toString();
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.4
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000409function NumberValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410 // NOTE: Both Number objects and values can enter here as
411 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000412 if (!IS_NUMBER(this) && !IS_NUMBER_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000413 throw new $TypeError('Number.prototype.valueOf is not generic');
414 return %_ValueOf(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000415}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416
417
418// ECMA-262 section 15.7.4.5
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000419function NumberToFixed(fractionDigits) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000420 var f = TO_INTEGER(fractionDigits);
421 if (f < 0 || f > 20) {
422 throw new $RangeError("toFixed() digits argument must be between 0 and 20");
423 }
424 var x = ToNumber(this);
425 return %NumberToFixed(x, f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000426}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000427
428
429// ECMA-262 section 15.7.4.6
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000430function NumberToExponential(fractionDigits) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000431 var f = -1;
432 if (!IS_UNDEFINED(fractionDigits)) {
433 f = TO_INTEGER(fractionDigits);
434 if (f < 0 || f > 20) {
435 throw new $RangeError("toExponential() argument must be between 0 and 20");
436 }
437 }
438 var x = ToNumber(this);
439 return %NumberToExponential(x, f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000440}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000441
442
443// ECMA-262 section 15.7.4.7
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000444function NumberToPrecision(precision) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000445 if (IS_UNDEFINED(precision)) return ToString(%_ValueOf(this));
446 var p = TO_INTEGER(precision);
447 if (p < 1 || p > 21) {
448 throw new $RangeError("toPrecision() argument must be between 1 and 21");
449 }
450 var x = ToNumber(this);
451 return %NumberToPrecision(x, p);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000452}
453
454
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000455function CheckJSONPrimitive(val) {
456 if (!IsPrimitive(val))
457 throw MakeTypeError('result_not_primitive', ['toJSON', val]);
458 return val;
459}
460
461
462function NumberToJSON(key) {
463 return CheckJSONPrimitive(this.valueOf());
464}
465
466
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000467// ----------------------------------------------------------------------------
468
469function SetupNumber() {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000470 %OptimizeObjectForAddingMultipleProperties($Number.prototype, 8);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000471 // Setup the constructor property on the Number prototype object.
472 %SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
473
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000474 %OptimizeObjectForAddingMultipleProperties($Number, 5);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000475 // ECMA-262 section 15.7.3.1.
476 %SetProperty($Number,
477 "MAX_VALUE",
478 1.7976931348623157e+308,
479 DONT_ENUM | DONT_DELETE | READ_ONLY);
480
481 // ECMA-262 section 15.7.3.2.
482 %SetProperty($Number, "MIN_VALUE", 5e-324, DONT_ENUM | DONT_DELETE | READ_ONLY);
483
484 // ECMA-262 section 15.7.3.3.
485 %SetProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
486
487 // ECMA-262 section 15.7.3.4.
488 %SetProperty($Number,
489 "NEGATIVE_INFINITY",
490 -1/0,
491 DONT_ENUM | DONT_DELETE | READ_ONLY);
492
493 // ECMA-262 section 15.7.3.5.
494 %SetProperty($Number,
495 "POSITIVE_INFINITY",
496 1/0,
497 DONT_ENUM | DONT_DELETE | READ_ONLY);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000498 %TransformToFastProperties($Number);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000499
500 // Setup non-enumerable functions on the Number prototype object.
501 InstallFunctions($Number.prototype, DONT_ENUM, $Array(
502 "toString", NumberToString,
503 "toLocaleString", NumberToLocaleString,
504 "valueOf", NumberValueOf,
505 "toFixed", NumberToFixed,
506 "toExponential", NumberToExponential,
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000507 "toPrecision", NumberToPrecision,
508 "toJSON", NumberToJSON
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000509 ));
510}
511
512SetupNumber();
513
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000514
515
516// ----------------------------------------------------------------------------
517// Function
518
519$Function.prototype.constructor = $Function;
520
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521function FunctionSourceString(func) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000522 if (!IS_FUNCTION(func)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000523 throw new $TypeError('Function.prototype.toString is not generic');
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000524 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525
526 var source = %FunctionGetSourceCode(func);
christian.plesner.hansen@gmail.com2bc58ef2009-09-22 10:00:30 +0000527 if (!IS_STRING(source) || %FunctionIsBuiltin(func)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528 var name = %FunctionGetName(func);
529 if (name) {
530 // Mimic what KJS does.
531 return 'function ' + name + '() { [native code] }';
532 } else {
533 return 'function () { [native code] }';
534 }
535 }
536
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000537 var name = %FunctionGetName(func);
538 return 'function ' + name + source;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000539}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000540
541
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000542function FunctionToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000543 return FunctionSourceString(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000544}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000545
546
547function NewFunction(arg1) { // length == 1
548 var n = %_ArgumentsLength();
549 var p = '';
550 if (n > 1) {
551 p = new $Array(n - 1);
552 // Explicitly convert all parameters to strings.
553 // Array.prototype.join replaces null with empty strings which is
554 // not appropriate.
555 for (var i = 0; i < n - 1; i++) p[i] = ToString(%_Arguments(i));
556 p = p.join(',');
557 // If the formal parameters string include ) - an illegal
558 // character - it may make the combined function expression
559 // compile. We avoid this problem by checking for this early on.
560 if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]);
561 }
562 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : '';
ager@chromium.org236ad962008-09-25 09:45:57 +0000563 var source = '(function(' + p + ') {\n' + body + '\n})';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000564
565 // The call to SetNewFunctionAttributes will ensure the prototype
566 // property of the resulting function is enumerable (ECMA262, 15.3.5.2).
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000567 var f = %CompileString(source, false)();
ager@chromium.org236ad962008-09-25 09:45:57 +0000568 %FunctionSetName(f, "anonymous");
569 return %SetNewFunctionAttributes(f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000570}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000571
572%SetCode($Function, NewFunction);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000573
574// ----------------------------------------------------------------------------
575
576function SetupFunction() {
577 InstallFunctions($Function.prototype, DONT_ENUM, $Array(
578 "toString", FunctionToString
579 ));
580}
581
582SetupFunction();