blob: 55bc9f8fff0b8c5ad5c7d6e39e59d8e755c5a891 [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.orga74f0da2008-12-03 16:05:52 +0000118 if (this !== global && this !== %GlobalReceiver(global)) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000119 throw new $EvalError('The "this" object passed to eval must ' +
120 'be the global object from which eval originated');
121 }
122
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000123 var f = %CompileString(x, 0, false);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000124 if (!IS_FUNCTION(f)) return f;
125
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000126 return f.call(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000127}
128
129
130// execScript for IE compatibility.
131function GlobalExecScript(expr, lang) {
132 // NOTE: We don't care about the character casing.
133 if (!lang || /javascript/i.test(lang)) {
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000134 var f = %CompileString(ToString(expr), 0, false);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000135 f.call(%GlobalReceiver(global));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000136 }
137 return null;
138}
139
140
141// ----------------------------------------------------------------------------
142
143
144function SetupGlobal() {
145 // ECMA 262 - 15.1.1.1.
146 %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
147
148 // ECMA-262 - 15.1.1.2.
149 %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE);
150
151 // ECMA-262 - 15.1.1.3.
152 %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000153
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000154 // Setup non-enumerable function on the global object.
155 InstallFunctions(global, DONT_ENUM, $Array(
156 "isNaN", GlobalIsNaN,
157 "isFinite", GlobalIsFinite,
158 "parseInt", GlobalParseInt,
159 "parseFloat", GlobalParseFloat,
160 "eval", GlobalEval,
161 "execScript", GlobalExecScript
162 ));
163}
164
165SetupGlobal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000166
167
168// ----------------------------------------------------------------------------
169// Boolean (first part of definition)
170
171
172%SetCode($Boolean, function(x) {
mads.s.ager31e71382008-08-13 09:32:07 +0000173 if (%IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174 %_SetValueOf(this, ToBoolean(x));
175 } else {
176 return ToBoolean(x);
177 }
178});
179
180%FunctionSetPrototype($Boolean, new $Boolean(false));
181
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000182%SetProperty($Boolean.prototype, "constructor", $Boolean, DONT_ENUM);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000183
184// ----------------------------------------------------------------------------
185// Object
186
187$Object.prototype.constructor = $Object;
188
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000189// ECMA-262 - 15.2.4.2
190function ObjectToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000191 var c = %ClassOf(this);
192 // Hide Arguments from the outside.
193 if (c === 'Arguments') c = 'Object';
194 return "[object " + c + "]";
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000195}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196
197
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000198// ECMA-262 - 15.2.4.3
199function ObjectToLocaleString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200 return this.toString();
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000201}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202
203
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000204// ECMA-262 - 15.2.4.4
205function ObjectValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000206 return this;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000207}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000208
209
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000210// ECMA-262 - 15.2.4.5
211function ObjectHasOwnProperty(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212 return %HasLocalProperty(ToObject(this), ToString(V));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000213}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214
215
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000216// ECMA-262 - 15.2.4.6
217function ObjectIsPrototypeOf(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000218 if (!IS_OBJECT(V) && !IS_FUNCTION(V)) return false;
219 return %IsInPrototypeChain(this, V);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000220}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221
222
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000223// ECMA-262 - 15.2.4.6
224function ObjectPropertyIsEnumerable(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000225 if (this == null) return false;
226 if (!IS_OBJECT(this) && !IS_FUNCTION(this)) return false;
227 return %IsPropertyEnumerable(this, ToString(V));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000228}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229
230
231// Extensions for providing property getters and setters.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000232function ObjectDefineGetter(name, fun) {
233 if (this == null) {
234 throw new $TypeError('Object.prototype.__defineGetter__: this is Null');
235 }
236 if (!IS_FUNCTION(fun)) {
237 throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
238 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000239 return %DefineAccessor(ToObject(this), ToString(name), GETTER, fun);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000240}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000241
242
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000243function ObjectLookupGetter(name) {
244 if (this == null) {
245 throw new $TypeError('Object.prototype.__lookupGetter__: this is Null');
246 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000247 return %LookupAccessor(ToObject(this), ToString(name), GETTER);
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 ObjectDefineSetter(name, fun) {
252 if (this == null) {
253 throw new $TypeError('Object.prototype.__defineSetter__: this is Null');
254 }
255 if (!IS_FUNCTION(fun)) {
256 throw new $TypeError(
257 'Object.prototype.__defineSetter__: Expecting function');
258 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000259 return %DefineAccessor(ToObject(this), ToString(name), SETTER, fun);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000260}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000261
262
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000263function ObjectLookupSetter(name) {
264 if (this == null) {
265 throw new $TypeError('Object.prototype.__lookupSetter__: this is Null');
266 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000267 return %LookupAccessor(ToObject(this), ToString(name), SETTER);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000268}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000269
270
271%SetCode($Object, function(x) {
mads.s.ager31e71382008-08-13 09:32:07 +0000272 if (%IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000273 if (x == null) return this;
274 return ToObject(x);
275 } else {
276 if (x == null) return { };
277 return ToObject(x);
278 }
279});
280
281
282// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000283
284
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000285function SetupObject() {
286 // Setup non-enumerable functions on the Object.prototype object.
287 InstallFunctions($Object.prototype, DONT_ENUM, $Array(
288 "toString", ObjectToString,
289 "toLocaleString", ObjectToLocaleString,
290 "valueOf", ObjectValueOf,
291 "hasOwnProperty", ObjectHasOwnProperty,
292 "isPrototypeOf", ObjectIsPrototypeOf,
293 "propertyIsEnumerable", ObjectPropertyIsEnumerable,
294 "__defineGetter__", ObjectDefineGetter,
295 "__lookupGetter__", ObjectLookupGetter,
296 "__defineSetter__", ObjectDefineSetter,
297 "__lookupSetter__", ObjectLookupSetter
298 ));
299}
300
301SetupObject();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000302
303
304// ----------------------------------------------------------------------------
305// Boolean
306
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000307function BooleanToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000308 // NOTE: Both Boolean objects and values can enter here as
309 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000310 if (!IS_BOOLEAN(this) && !%HasBooleanClass(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000311 throw new $TypeError('Boolean.prototype.toString is not generic');
312 return ToString(%_ValueOf(this));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000313}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000314
315
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000316function BooleanValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000317 // NOTE: Both Boolean objects and values can enter here as
318 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000319 if (!IS_BOOLEAN(this) && !%HasBooleanClass(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320 throw new $TypeError('Boolean.prototype.valueOf is not generic');
321 return %_ValueOf(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000322}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000323
324
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000325function BooleanToJSON(key) {
326 return CheckJSONPrimitive(this.valueOf());
327}
328
329
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000330// ----------------------------------------------------------------------------
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000331
332
333function SetupBoolean() {
334 InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
335 "toString", BooleanToString,
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000336 "valueOf", BooleanValueOf,
337 "toJSON", BooleanToJSON
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000338 ));
339}
340
341SetupBoolean();
342
343// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000344// Number
345
346// Set the Number function and constructor.
347%SetCode($Number, function(x) {
348 var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x);
mads.s.ager31e71382008-08-13 09:32:07 +0000349 if (%IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000350 %_SetValueOf(this, value);
351 } else {
352 return value;
353 }
354});
355
356%FunctionSetPrototype($Number, new $Number(0));
357
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000358// ECMA-262 section 15.7.4.2.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000359function NumberToString(radix) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000360 // NOTE: Both Number objects and values can enter here as
361 // 'this'. This is not as dictated by ECMA-262.
362 var number = this;
363 if (!IS_NUMBER(this)) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000364 if (!%HasNumberClass(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000365 throw new $TypeError('Number.prototype.toString is not generic');
366 // Get the value of this number in case it's an object.
367 number = %_ValueOf(this);
368 }
369 // Fast case: Convert number in radix 10.
370 if (IS_UNDEFINED(radix) || radix === 10) {
371 return ToString(number);
372 }
373
374 // Convert the radix to an integer and check the range.
375 radix = TO_INTEGER(radix);
376 if (radix < 2 || radix > 36) {
377 throw new $RangeError('toString() radix argument must be between 2 and 36');
378 }
379 // Convert the number to a string in the given radix.
380 return %NumberToRadixString(number, radix);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000381}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000382
383
384// ECMA-262 section 15.7.4.3
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000385function NumberToLocaleString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000386 return this.toString();
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000387}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000388
389
390// ECMA-262 section 15.7.4.4
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000391function NumberValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000392 // NOTE: Both Number objects and values can enter here as
393 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000394 if (!IS_NUMBER(this) && !%HasNumberClass(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000395 throw new $TypeError('Number.prototype.valueOf is not generic');
396 return %_ValueOf(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000397}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398
399
400// ECMA-262 section 15.7.4.5
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000401function NumberToFixed(fractionDigits) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000402 var f = TO_INTEGER(fractionDigits);
403 if (f < 0 || f > 20) {
404 throw new $RangeError("toFixed() digits argument must be between 0 and 20");
405 }
406 var x = ToNumber(this);
407 return %NumberToFixed(x, f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000408}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000409
410
411// ECMA-262 section 15.7.4.6
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000412function NumberToExponential(fractionDigits) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000413 var f = -1;
414 if (!IS_UNDEFINED(fractionDigits)) {
415 f = TO_INTEGER(fractionDigits);
416 if (f < 0 || f > 20) {
417 throw new $RangeError("toExponential() argument must be between 0 and 20");
418 }
419 }
420 var x = ToNumber(this);
421 return %NumberToExponential(x, f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000422}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000423
424
425// ECMA-262 section 15.7.4.7
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000426function NumberToPrecision(precision) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000427 if (IS_UNDEFINED(precision)) return ToString(%_ValueOf(this));
428 var p = TO_INTEGER(precision);
429 if (p < 1 || p > 21) {
430 throw new $RangeError("toPrecision() argument must be between 1 and 21");
431 }
432 var x = ToNumber(this);
433 return %NumberToPrecision(x, p);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000434}
435
436
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000437function CheckJSONPrimitive(val) {
438 if (!IsPrimitive(val))
439 throw MakeTypeError('result_not_primitive', ['toJSON', val]);
440 return val;
441}
442
443
444function NumberToJSON(key) {
445 return CheckJSONPrimitive(this.valueOf());
446}
447
448
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000449// ----------------------------------------------------------------------------
450
451function SetupNumber() {
452 // Setup the constructor property on the Number prototype object.
453 %SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
454
455 // ECMA-262 section 15.7.3.1.
456 %SetProperty($Number,
457 "MAX_VALUE",
458 1.7976931348623157e+308,
459 DONT_ENUM | DONT_DELETE | READ_ONLY);
460
461 // ECMA-262 section 15.7.3.2.
462 %SetProperty($Number, "MIN_VALUE", 5e-324, DONT_ENUM | DONT_DELETE | READ_ONLY);
463
464 // ECMA-262 section 15.7.3.3.
465 %SetProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
466
467 // ECMA-262 section 15.7.3.4.
468 %SetProperty($Number,
469 "NEGATIVE_INFINITY",
470 -1/0,
471 DONT_ENUM | DONT_DELETE | READ_ONLY);
472
473 // ECMA-262 section 15.7.3.5.
474 %SetProperty($Number,
475 "POSITIVE_INFINITY",
476 1/0,
477 DONT_ENUM | DONT_DELETE | READ_ONLY);
478
479 // Setup non-enumerable functions on the Number prototype object.
480 InstallFunctions($Number.prototype, DONT_ENUM, $Array(
481 "toString", NumberToString,
482 "toLocaleString", NumberToLocaleString,
483 "valueOf", NumberValueOf,
484 "toFixed", NumberToFixed,
485 "toExponential", NumberToExponential,
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000486 "toPrecision", NumberToPrecision,
487 "toJSON", NumberToJSON
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000488 ));
489}
490
491SetupNumber();
492
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493
494
495// ----------------------------------------------------------------------------
496// Function
497
498$Function.prototype.constructor = $Function;
499
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000500function FunctionSourceString(func) {
501 // NOTE: Both Function objects and values can enter here as
502 // 'func'. This is not as dictated by ECMA-262.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000503 if (!IS_FUNCTION(func) && !%HasFunctionClass(func))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504 throw new $TypeError('Function.prototype.toString is not generic');
505
506 var source = %FunctionGetSourceCode(func);
507 if (!IS_STRING(source)) {
508 var name = %FunctionGetName(func);
509 if (name) {
510 // Mimic what KJS does.
511 return 'function ' + name + '() { [native code] }';
512 } else {
513 return 'function () { [native code] }';
514 }
515 }
516
517 // Censor occurrences of internal calls. We do that for all
518 // functions and don't cache under the assumption that people rarly
519 // convert functions to strings. Note that we (apparently) can't
520 // use regular expression literals in natives files.
521 var regexp = ORIGINAL_REGEXP("%(\\w+\\()", "gm");
522 if (source.match(regexp)) source = source.replace(regexp, "$1");
523 var name = %FunctionGetName(func);
524 return 'function ' + name + source;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000525}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000526
527
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000528function FunctionToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000529 return FunctionSourceString(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000530}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000531
532
533function NewFunction(arg1) { // length == 1
534 var n = %_ArgumentsLength();
535 var p = '';
536 if (n > 1) {
537 p = new $Array(n - 1);
538 // Explicitly convert all parameters to strings.
539 // Array.prototype.join replaces null with empty strings which is
540 // not appropriate.
541 for (var i = 0; i < n - 1; i++) p[i] = ToString(%_Arguments(i));
542 p = p.join(',');
543 // If the formal parameters string include ) - an illegal
544 // character - it may make the combined function expression
545 // compile. We avoid this problem by checking for this early on.
546 if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]);
547 }
548 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : '';
ager@chromium.org236ad962008-09-25 09:45:57 +0000549 var source = '(function(' + p + ') {\n' + body + '\n})';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000550
551 // The call to SetNewFunctionAttributes will ensure the prototype
552 // property of the resulting function is enumerable (ECMA262, 15.3.5.2).
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000553 var f = %CompileString(source, -1, false)();
ager@chromium.org236ad962008-09-25 09:45:57 +0000554 %FunctionSetName(f, "anonymous");
555 return %SetNewFunctionAttributes(f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000556}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000557
558%SetCode($Function, NewFunction);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000559
560// ----------------------------------------------------------------------------
561
562function SetupFunction() {
563 InstallFunctions($Function.prototype, DONT_ENUM, $Array(
564 "toString", FunctionToString
565 ));
566}
567
568SetupFunction();
569