blob: fe463513d971bda62e228183ff8b7bb785548b25 [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) {
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}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000056
ager@chromium.org9085a012009-05-11 19:22:57 +000057// Emulates JSC by installing functions on a hidden prototype that
58// lies above the current object/prototype. This lets you override
59// functions on String.prototype etc. and then restore the old function
60// with delete. See http://code.google.com/p/chromium/issues/detail?id=1717
61function InstallFunctionsOnHiddenPrototype(object, attributes, functions) {
62 var hidden_prototype = new $Object();
63 %SetHiddenPrototype(object, hidden_prototype);
64 InstallFunctions(hidden_prototype, attributes, functions);
65}
66
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000067
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000068// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000069
70
71// ECMA 262 - 15.1.4
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000072function GlobalIsNaN(number) {
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +000073 var n = ToNumber(number);
74 return NUMBER_IS_NAN(n);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000075}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000076
77
78// ECMA 262 - 15.1.5
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000079function GlobalIsFinite(number) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080 return %NumberIsFinite(ToNumber(number));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000081}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000082
83
84// ECMA-262 - 15.1.2.2
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000085function GlobalParseInt(string, radix) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000086 if (radix === void 0) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000087 // Some people use parseInt instead of Math.floor. This
88 // optimization makes parseInt on a Smi 12 times faster (60ns
89 // vs 800ns). The following optimization makes parseInt on a
90 // non-Smi number 9 times faster (230ns vs 2070ns). Together
91 // they make parseInt on a string 1.4% slower (274ns vs 270ns).
92 if (%_IsSmi(string)) return string;
ager@chromium.org381abbb2009-02-25 13:23:22 +000093 if (IS_NUMBER(string) &&
94 ((string < -0.01 && -1e9 < string) ||
95 (0.01 < string && string < 1e9))) {
96 // Truncate number.
97 return string | 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000098 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000099 radix = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000100 } else {
101 radix = TO_INT32(radix);
102 if (!(radix == 0 || (2 <= radix && radix <= 36)))
103 return $NaN;
104 }
105 return %StringParseInt(ToString(string), radix);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000106}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107
108
109// ECMA-262 - 15.1.2.3
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000110function GlobalParseFloat(string) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000111 return %StringParseFloat(ToString(string));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000112}
113
114
115function GlobalEval(x) {
116 if (!IS_STRING(x)) return x;
117
ager@chromium.orge2902be2009-06-08 12:21:35 +0000118 var global_receiver = %GlobalReceiver(global);
119 var this_is_global_receiver = (this === global_receiver);
120 var global_is_detached = (global === global_receiver);
121
122 if (!this_is_global_receiver || global_is_detached) {
123 throw new $EvalError('The "this" object passed to eval must ' +
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000124 'be the global object from which eval originated');
125 }
ager@chromium.orge2902be2009-06-08 12:21:35 +0000126
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000127 var f = %CompileString(x, false);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000128 if (!IS_FUNCTION(f)) return f;
129
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000130 return f.call(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000131}
132
133
134// execScript for IE compatibility.
135function GlobalExecScript(expr, lang) {
136 // NOTE: We don't care about the character casing.
137 if (!lang || /javascript/i.test(lang)) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000138 var f = %CompileString(ToString(expr), false);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000139 f.call(%GlobalReceiver(global));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000140 }
141 return null;
142}
143
144
145// ----------------------------------------------------------------------------
146
147
148function SetupGlobal() {
149 // ECMA 262 - 15.1.1.1.
150 %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
151
152 // ECMA-262 - 15.1.1.2.
153 %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE);
154
155 // ECMA-262 - 15.1.1.3.
156 %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000157
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000158 // Setup non-enumerable function on the global object.
159 InstallFunctions(global, DONT_ENUM, $Array(
160 "isNaN", GlobalIsNaN,
161 "isFinite", GlobalIsFinite,
162 "parseInt", GlobalParseInt,
163 "parseFloat", GlobalParseFloat,
164 "eval", GlobalEval,
165 "execScript", GlobalExecScript
166 ));
167}
168
169SetupGlobal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000170
171
172// ----------------------------------------------------------------------------
173// Boolean (first part of definition)
174
175
176%SetCode($Boolean, function(x) {
mads.s.ager31e71382008-08-13 09:32:07 +0000177 if (%IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178 %_SetValueOf(this, ToBoolean(x));
179 } else {
180 return ToBoolean(x);
181 }
182});
183
184%FunctionSetPrototype($Boolean, new $Boolean(false));
185
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000186%SetProperty($Boolean.prototype, "constructor", $Boolean, DONT_ENUM);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000187
188// ----------------------------------------------------------------------------
189// Object
190
191$Object.prototype.constructor = $Object;
192
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000193// ECMA-262 - 15.2.4.2
194function ObjectToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195 var c = %ClassOf(this);
196 // Hide Arguments from the outside.
197 if (c === 'Arguments') c = 'Object';
198 return "[object " + c + "]";
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000199}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200
201
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000202// ECMA-262 - 15.2.4.3
203function ObjectToLocaleString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000204 return this.toString();
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000205}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000206
207
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000208// ECMA-262 - 15.2.4.4
209function ObjectValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210 return this;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000211}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212
213
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000214// ECMA-262 - 15.2.4.5
215function ObjectHasOwnProperty(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216 return %HasLocalProperty(ToObject(this), ToString(V));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000217}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000218
219
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000220// ECMA-262 - 15.2.4.6
221function ObjectIsPrototypeOf(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222 if (!IS_OBJECT(V) && !IS_FUNCTION(V)) return false;
223 return %IsInPrototypeChain(this, V);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000224}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000225
226
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000227// ECMA-262 - 15.2.4.6
228function ObjectPropertyIsEnumerable(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229 if (this == null) return false;
230 if (!IS_OBJECT(this) && !IS_FUNCTION(this)) return false;
231 return %IsPropertyEnumerable(this, ToString(V));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000232}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000233
234
235// Extensions for providing property getters and setters.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000236function ObjectDefineGetter(name, fun) {
237 if (this == null) {
238 throw new $TypeError('Object.prototype.__defineGetter__: this is Null');
239 }
240 if (!IS_FUNCTION(fun)) {
241 throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
242 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000243 return %DefineAccessor(ToObject(this), ToString(name), GETTER, fun);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000244}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000245
246
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000247function ObjectLookupGetter(name) {
248 if (this == null) {
249 throw new $TypeError('Object.prototype.__lookupGetter__: this is Null');
250 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251 return %LookupAccessor(ToObject(this), ToString(name), GETTER);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000252}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000253
254
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000255function ObjectDefineSetter(name, fun) {
256 if (this == null) {
257 throw new $TypeError('Object.prototype.__defineSetter__: this is Null');
258 }
259 if (!IS_FUNCTION(fun)) {
260 throw new $TypeError(
261 'Object.prototype.__defineSetter__: Expecting function');
262 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000263 return %DefineAccessor(ToObject(this), ToString(name), SETTER, fun);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000264}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000265
266
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000267function ObjectLookupSetter(name) {
268 if (this == null) {
269 throw new $TypeError('Object.prototype.__lookupSetter__: this is Null');
270 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000271 return %LookupAccessor(ToObject(this), ToString(name), SETTER);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000272}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000273
274
275%SetCode($Object, function(x) {
mads.s.ager31e71382008-08-13 09:32:07 +0000276 if (%IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000277 if (x == null) return this;
278 return ToObject(x);
279 } else {
280 if (x == null) return { };
281 return ToObject(x);
282 }
283});
284
285
286// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000287
288
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000289function SetupObject() {
290 // Setup non-enumerable functions on the Object.prototype object.
291 InstallFunctions($Object.prototype, DONT_ENUM, $Array(
292 "toString", ObjectToString,
293 "toLocaleString", ObjectToLocaleString,
294 "valueOf", ObjectValueOf,
295 "hasOwnProperty", ObjectHasOwnProperty,
296 "isPrototypeOf", ObjectIsPrototypeOf,
297 "propertyIsEnumerable", ObjectPropertyIsEnumerable,
298 "__defineGetter__", ObjectDefineGetter,
299 "__lookupGetter__", ObjectLookupGetter,
300 "__defineSetter__", ObjectDefineSetter,
301 "__lookupSetter__", ObjectLookupSetter
302 ));
303}
304
305SetupObject();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000306
307
308// ----------------------------------------------------------------------------
309// Boolean
310
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000311function BooleanToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000312 // NOTE: Both Boolean objects and values can enter here as
313 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000314 if (!IS_BOOLEAN(this) && !%HasBooleanClass(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315 throw new $TypeError('Boolean.prototype.toString is not generic');
316 return ToString(%_ValueOf(this));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000317}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000318
319
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000320function BooleanValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321 // NOTE: Both Boolean objects and values can enter here as
322 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000323 if (!IS_BOOLEAN(this) && !%HasBooleanClass(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000324 throw new $TypeError('Boolean.prototype.valueOf is not generic');
325 return %_ValueOf(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000326}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000327
328
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000329function BooleanToJSON(key) {
330 return CheckJSONPrimitive(this.valueOf());
331}
332
333
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000334// ----------------------------------------------------------------------------
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000335
336
337function SetupBoolean() {
338 InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
339 "toString", BooleanToString,
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000340 "valueOf", BooleanValueOf,
341 "toJSON", BooleanToJSON
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000342 ));
343}
344
345SetupBoolean();
346
347// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000348// Number
349
350// Set the Number function and constructor.
351%SetCode($Number, function(x) {
352 var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x);
mads.s.ager31e71382008-08-13 09:32:07 +0000353 if (%IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000354 %_SetValueOf(this, value);
355 } else {
356 return value;
357 }
358});
359
360%FunctionSetPrototype($Number, new $Number(0));
361
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000362// ECMA-262 section 15.7.4.2.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000363function NumberToString(radix) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000364 // NOTE: Both Number objects and values can enter here as
365 // 'this'. This is not as dictated by ECMA-262.
366 var number = this;
367 if (!IS_NUMBER(this)) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000368 if (!%HasNumberClass(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000369 throw new $TypeError('Number.prototype.toString is not generic');
370 // Get the value of this number in case it's an object.
371 number = %_ValueOf(this);
372 }
373 // Fast case: Convert number in radix 10.
374 if (IS_UNDEFINED(radix) || radix === 10) {
375 return ToString(number);
376 }
377
378 // Convert the radix to an integer and check the range.
379 radix = TO_INTEGER(radix);
380 if (radix < 2 || radix > 36) {
381 throw new $RangeError('toString() radix argument must be between 2 and 36');
382 }
383 // Convert the number to a string in the given radix.
384 return %NumberToRadixString(number, radix);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000385}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000386
387
388// ECMA-262 section 15.7.4.3
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000389function NumberToLocaleString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000390 return this.toString();
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000391}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000392
393
394// ECMA-262 section 15.7.4.4
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000395function NumberValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000396 // NOTE: Both Number objects and values can enter here as
397 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000398 if (!IS_NUMBER(this) && !%HasNumberClass(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000399 throw new $TypeError('Number.prototype.valueOf is not generic');
400 return %_ValueOf(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000401}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000402
403
404// ECMA-262 section 15.7.4.5
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000405function NumberToFixed(fractionDigits) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000406 var f = TO_INTEGER(fractionDigits);
407 if (f < 0 || f > 20) {
408 throw new $RangeError("toFixed() digits argument must be between 0 and 20");
409 }
410 var x = ToNumber(this);
411 return %NumberToFixed(x, f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000412}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000413
414
415// ECMA-262 section 15.7.4.6
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000416function NumberToExponential(fractionDigits) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000417 var f = -1;
418 if (!IS_UNDEFINED(fractionDigits)) {
419 f = TO_INTEGER(fractionDigits);
420 if (f < 0 || f > 20) {
421 throw new $RangeError("toExponential() argument must be between 0 and 20");
422 }
423 }
424 var x = ToNumber(this);
425 return %NumberToExponential(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.7
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000430function NumberToPrecision(precision) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000431 if (IS_UNDEFINED(precision)) return ToString(%_ValueOf(this));
432 var p = TO_INTEGER(precision);
433 if (p < 1 || p > 21) {
434 throw new $RangeError("toPrecision() argument must be between 1 and 21");
435 }
436 var x = ToNumber(this);
437 return %NumberToPrecision(x, p);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000438}
439
440
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000441function CheckJSONPrimitive(val) {
442 if (!IsPrimitive(val))
443 throw MakeTypeError('result_not_primitive', ['toJSON', val]);
444 return val;
445}
446
447
448function NumberToJSON(key) {
449 return CheckJSONPrimitive(this.valueOf());
450}
451
452
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000453// ----------------------------------------------------------------------------
454
455function SetupNumber() {
456 // Setup the constructor property on the Number prototype object.
457 %SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
458
459 // ECMA-262 section 15.7.3.1.
460 %SetProperty($Number,
461 "MAX_VALUE",
462 1.7976931348623157e+308,
463 DONT_ENUM | DONT_DELETE | READ_ONLY);
464
465 // ECMA-262 section 15.7.3.2.
466 %SetProperty($Number, "MIN_VALUE", 5e-324, DONT_ENUM | DONT_DELETE | READ_ONLY);
467
468 // ECMA-262 section 15.7.3.3.
469 %SetProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
470
471 // ECMA-262 section 15.7.3.4.
472 %SetProperty($Number,
473 "NEGATIVE_INFINITY",
474 -1/0,
475 DONT_ENUM | DONT_DELETE | READ_ONLY);
476
477 // ECMA-262 section 15.7.3.5.
478 %SetProperty($Number,
479 "POSITIVE_INFINITY",
480 1/0,
481 DONT_ENUM | DONT_DELETE | READ_ONLY);
482
483 // Setup non-enumerable functions on the Number prototype object.
484 InstallFunctions($Number.prototype, DONT_ENUM, $Array(
485 "toString", NumberToString,
486 "toLocaleString", NumberToLocaleString,
487 "valueOf", NumberValueOf,
488 "toFixed", NumberToFixed,
489 "toExponential", NumberToExponential,
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000490 "toPrecision", NumberToPrecision,
491 "toJSON", NumberToJSON
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000492 ));
493}
494
495SetupNumber();
496
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000497
498
499// ----------------------------------------------------------------------------
500// Function
501
502$Function.prototype.constructor = $Function;
503
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504function FunctionSourceString(func) {
505 // NOTE: Both Function objects and values can enter here as
506 // 'func'. This is not as dictated by ECMA-262.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000507 if (!IS_FUNCTION(func) && !%HasFunctionClass(func))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508 throw new $TypeError('Function.prototype.toString is not generic');
509
510 var source = %FunctionGetSourceCode(func);
511 if (!IS_STRING(source)) {
512 var name = %FunctionGetName(func);
513 if (name) {
514 // Mimic what KJS does.
515 return 'function ' + name + '() { [native code] }';
516 } else {
517 return 'function () { [native code] }';
518 }
519 }
520
521 // Censor occurrences of internal calls. We do that for all
522 // functions and don't cache under the assumption that people rarly
523 // convert functions to strings. Note that we (apparently) can't
524 // use regular expression literals in natives files.
525 var regexp = ORIGINAL_REGEXP("%(\\w+\\()", "gm");
526 if (source.match(regexp)) source = source.replace(regexp, "$1");
527 var name = %FunctionGetName(func);
528 return 'function ' + name + source;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000529}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000530
531
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000532function FunctionToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000533 return FunctionSourceString(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000534}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000535
536
537function NewFunction(arg1) { // length == 1
538 var n = %_ArgumentsLength();
539 var p = '';
540 if (n > 1) {
541 p = new $Array(n - 1);
542 // Explicitly convert all parameters to strings.
543 // Array.prototype.join replaces null with empty strings which is
544 // not appropriate.
545 for (var i = 0; i < n - 1; i++) p[i] = ToString(%_Arguments(i));
546 p = p.join(',');
547 // If the formal parameters string include ) - an illegal
548 // character - it may make the combined function expression
549 // compile. We avoid this problem by checking for this early on.
550 if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]);
551 }
552 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : '';
ager@chromium.org236ad962008-09-25 09:45:57 +0000553 var source = '(function(' + p + ') {\n' + body + '\n})';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000554
555 // The call to SetNewFunctionAttributes will ensure the prototype
556 // property of the resulting function is enumerable (ECMA262, 15.3.5.2).
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000557 var f = %CompileString(source, false)();
ager@chromium.org236ad962008-09-25 09:45:57 +0000558 %FunctionSetName(f, "anonymous");
559 return %SetNewFunctionAttributes(f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000560}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000561
562%SetCode($Function, NewFunction);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000563
564// ----------------------------------------------------------------------------
565
566function SetupFunction() {
567 InstallFunctions($Function.prototype, DONT_ENUM, $Array(
568 "toString", FunctionToString
569 ));
570}
571
572SetupFunction();
573