blob: 5e73d4100d643e35aadda8cbd9ab4ed1c62d541a [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
28// This files contains runtime support implemented in JavaScript.
29
30// CAUTION: Some of the functions specified in this file are called
31// directly from compiled code. These are the functions with names in
32// ALL CAPS. The compiled code passes the first argument in 'this' and
33// it does not push the function onto the stack. This means that you
34// cannot use contexts in all these functions.
35
36
37/* -----------------------------------
38 - - - C o m p a r i s o n - - -
39 -----------------------------------
40*/
41
42// The following const declarations are shared with other native JS files.
43// They are all declared at this one spot to avoid const redeclaration errors.
44const $Object = global.Object;
45const $Array = global.Array;
46const $String = global.String;
47const $Number = global.Number;
48const $Function = global.Function;
49const $Boolean = global.Boolean;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000050const $NaN = 0/0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000051
52
53// ECMA-262, section 11.9.1, page 55.
54function EQUALS(y) {
ager@chromium.org7c537e22008-10-16 08:43:32 +000055 if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000056 var x = this;
57
58 // NOTE: We use iteration instead of recursion, because it is
59 // difficult to call EQUALS with the correct setting of 'this' in
60 // an efficient way.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000061 while (true) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000062 if (IS_NUMBER(x)) {
63 if (y == null) return 1; // not equal
64 return %NumberEquals(x, %ToNumber(y));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000065 } else if (IS_STRING(x)) {
66 if (IS_STRING(y)) return %StringEquals(x, y);
67 if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
68 if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
69 if (y == null) return 1; // not equal
70 y = %ToPrimitive(y, NO_HINT);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000071 } else if (IS_BOOLEAN(x)) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000072 if (IS_BOOLEAN(y)) {
73 return %_ObjectEquals(x, y) ? 0 : 1;
74 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000075 if (y == null) return 1; // not equal
76 return %NumberEquals(%ToNumber(x), %ToNumber(y));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000077 } else if (x == null) {
78 // NOTE: This checks for both null and undefined.
79 return (y == null) ? 0 : 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080 } else {
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +000081 // x is not a number, boolean, null or undefined.
82 if (y == null) return 1; // not equal
ager@chromium.org9258b6b2008-09-11 09:11:10 +000083 if (IS_OBJECT(y)) {
84 return %_ObjectEquals(x, y) ? 0 : 1;
85 }
86 if (IS_FUNCTION(y)) {
87 return %_ObjectEquals(x, y) ? 0 : 1;
88 }
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +000089
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000090 x = %ToPrimitive(x, NO_HINT);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000091 }
92 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000093}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000094
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000095// ECMA-262, section 11.9.4, page 56.
96function STRICT_EQUALS(x) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000097 if (IS_STRING(this)) {
98 if (!IS_STRING(x)) return 1; // not equal
99 return %StringEquals(this, x);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000100 }
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000101
ager@chromium.org7c537e22008-10-16 08:43:32 +0000102 if (IS_NUMBER(this)) {
103 if (!IS_NUMBER(x)) return 1; // not equal
104 return %NumberEquals(this, x);
105 }
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000106
ager@chromium.org7c537e22008-10-16 08:43:32 +0000107 if (IS_UNDEFINED(this)) {
108 // Both undefined and undetectable.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000109 return IS_UNDEFINED(x) ? 0 : 1;
110 }
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000111
ager@chromium.org7c537e22008-10-16 08:43:32 +0000112 // Objects, null, booleans and functions are all that's left.
113 // They can all be compared with a simple identity check.
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000114 return %_ObjectEquals(this, x) ? 0 : 1;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000115}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000116
117
118// ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as
119// the result when either (or both) the operands are NaN.
120function COMPARE(x, ncr) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000121 // Fast case for numbers and strings.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122 if (IS_NUMBER(this) && IS_NUMBER(x)) {
123 return %NumberCompare(this, x, ncr);
124 }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000125 if (IS_STRING(this) && IS_STRING(x)) {
126 return %StringCompare(this, x);
127 }
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000128
ager@chromium.org7c537e22008-10-16 08:43:32 +0000129 // Default implementation.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000130 var a = %ToPrimitive(this, NUMBER_HINT);
131 var b = %ToPrimitive(x, NUMBER_HINT);
132 if (IS_STRING(a) && IS_STRING(b)) {
133 return %StringCompare(a, b);
134 } else {
135 return %NumberCompare(%ToNumber(a), %ToNumber(b), ncr);
136 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000137}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000138
139
140
141/* -----------------------------------
142 - - - A r i t h m e t i c - - -
143 -----------------------------------
144*/
145
146// ECMA-262, section 11.6.1, page 50.
147function ADD(x) {
148 // Fast case: Check for number operands and do the addition.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000149 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
150 if (IS_STRING(this) && IS_STRING(x)) return %StringAdd(this, x);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000151
ager@chromium.org7c537e22008-10-16 08:43:32 +0000152 // Default implementation.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000153 var a = %ToPrimitive(this, NO_HINT);
154 var b = %ToPrimitive(x, NO_HINT);
155
156 if (IS_STRING(a)) {
157 return %StringAdd(a, %ToString(b));
158 } else if (IS_STRING(b)) {
159 return %StringAdd(%ToString(a), b);
160 } else {
161 return %NumberAdd(%ToNumber(a), %ToNumber(b));
162 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000163}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000164
165
166// ECMA-262, section 11.6.2, page 50.
167function SUB(x) {
168 return %NumberSub(%ToNumber(this), %ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000169}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000170
171
172// ECMA-262, section 11.5.1, page 48.
173function MUL(x) {
174 return %NumberMul(%ToNumber(this), %ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000175}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176
177
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178// ECMA-262, section 11.5.2, page 49.
179function DIV(x) {
180 return %NumberDiv(%ToNumber(this), %ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000181}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182
183
184// ECMA-262, section 11.5.3, page 49.
185function MOD(x) {
186 return %NumberMod(%ToNumber(this), %ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000187}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188
189
190// ECMA-262, section 11.4.4, page 47.
191function INC() {
192 return %NumberAdd(%ToNumber(this), 1);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000193}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000194
195
196// ECMA-262, section 11.4.5, page 48.
197function DEC() {
198 return %NumberSub(%ToNumber(this), 1);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000199}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200
201
202
203/* -------------------------------------------
204 - - - B i t o p e r a t i o n s - - -
205 -------------------------------------------
206*/
207
208// ECMA-262, section 11.10, page 57.
209function BIT_OR(x) {
210 return %NumberOr(%ToNumber(this), %ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000211}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212
213
214// ECMA-262, section 11.10, page 57.
215function BIT_AND(x) {
216 return %NumberAnd(%ToNumber(this), %ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000217}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000218
219
220// ECMA-262, section 11.10, page 57.
221function BIT_XOR(x) {
222 return %NumberXor(%ToNumber(this), %ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000223}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000224
225
226// ECMA-262, section 11.4.7, page 47.
227function UNARY_MINUS() {
228 return %NumberUnaryMinus(%ToNumber(this));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000229}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000230
231
232// ECMA-262, section 11.4.8, page 48.
233function BIT_NOT() {
234 return %NumberNot(%ToNumber(this));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000235}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000236
237
238// ECMA-262, section 11.7.1, page 51.
239function SHL(x) {
240 return %NumberShl(%ToNumber(this), %ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000241}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000242
243
244// ECMA-262, section 11.7.2, page 51.
245function SAR(x) {
246 return %NumberSar(%ToNumber(this), %ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000247}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000248
249
250// ECMA-262, section 11.7.3, page 52.
251function SHR(x) {
252 return %NumberShr(%ToNumber(this), %ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000253}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000254
255
256
257/* -----------------------------
258 - - - H e l p e r s - - -
259 -----------------------------
260*/
261
262// ECMA-262, section 11.4.1, page 46.
263function DELETE(key) {
264 return %DeleteProperty(%ToObject(this), %ToString(key));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000265}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000266
267
268// ECMA-262, section 11.8.7, page 54.
269function IN(x) {
270 if (x == null || (!IS_OBJECT(x) && !IS_FUNCTION(x))) {
271 throw %MakeTypeError('invalid_in_operator_use', [this, x]);
272 }
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000273 return %_IsNonNegativeSmi(this) ? %HasElement(x, this) : %HasProperty(x, %ToString(this));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000274}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000275
276
ager@chromium.org7c537e22008-10-16 08:43:32 +0000277// ECMA-262, section 11.8.6, page 54. To make the implementation more
278// efficient, the return value should be zero if the 'this' is an
279// instance of F, and non-zero if not. This makes it possible to avoid
280// an expensive ToBoolean conversion in the generated code.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000281function INSTANCE_OF(F) {
282 var V = this;
283 if (!IS_FUNCTION(F)) {
284 throw %MakeTypeError('instanceof_function_expected', [V]);
285 }
286
287 // If V is not an object, return false.
288 if (IS_NULL(V) || (!IS_OBJECT(V) && !IS_FUNCTION(V))) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000289 return 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000290 }
291
292 // Get the prototype of F; if it is not an object, throw an error.
293 var O = F.prototype;
294 if (IS_NULL(O) || (!IS_OBJECT(O) && !IS_FUNCTION(O))) {
295 throw %MakeTypeError('instanceof_nonobject_proto', [O]);
296 }
297
298 // Return whether or not O is in the prototype chain of V.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000299 return %IsInPrototypeChain(O, V) ? 0 : 1;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000300}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000301
302
303// Get an array of property keys for the given object. Used in
304// for-in statements.
305function GET_KEYS() {
306 return %GetPropertyNames(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000307}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000308
309
310// Filter a given key against an object by checking if the object
311// has a property with the given key; return the key as a string if
312// it has. Otherwise returns null. Used in for-in statements.
313function FILTER_KEY(key) {
314 var string = %ToString(key);
315 if (%HasProperty(this, string)) return string;
316 return null;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000317}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000318
319
320function CALL_NON_FUNCTION() {
mads.s.ager31e71382008-08-13 09:32:07 +0000321 var callee = %GetCalledFunction();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000322 var delegate = %GetFunctionDelegate(callee);
323 if (!IS_FUNCTION(delegate)) {
324 throw %MakeTypeError('called_non_callable', [typeof callee]);
325 }
326
327 var parameters = %NewArguments(delegate);
328 return delegate.apply(callee, parameters);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000329}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000330
331
332function APPLY_PREPARE(args) {
333 var length;
334 // First check whether length is a positive Smi and args is an array. This is the
335 // fast case. If this fails, we do the slow case that takes care of more eventualities
336 if (%_IsArray(args)) {
337 length = args.length;
338 if (%_IsSmi(length) && length >= 0 && length < 0x800000 && IS_FUNCTION(this)) {
339 return length;
340 }
341 }
342
343 length = (args == null) ? 0 : %ToUint32(args.length);
344
345 // We can handle any number of apply arguments if the stack is
346 // big enough, but sanity check the value to avoid overflow when
347 // multiplying with pointer size.
348 if (length > 0x800000) {
349 throw %MakeRangeError('apply_overflow', [length]);
350 }
351
352 if (!IS_FUNCTION(this)) {
353 throw %MakeTypeError('apply_non_function', [ %ToString(this), typeof this ]);
354 }
355
356 // Make sure the arguments list has the right type.
357 if (args != null &&
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000358 !%HasArrayClass(args) &&
359 !%HasArgumentsClass(args)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000360 throw %MakeTypeError('apply_wrong_args', []);
361 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000362
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000363 // Return the length which is the number of arguments to copy to the
364 // stack. It is guaranteed to be a small integer at this point.
365 return length;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000366}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000367
368
369function APPLY_OVERFLOW(length) {
370 throw %MakeRangeError('apply_overflow', [length]);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000371}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000372
373
374// Convert the receiver to an object - forward to ToObject.
375function TO_OBJECT() {
376 return %ToObject(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000377}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000378
379
380// Convert the receiver to a number - forward to ToNumber.
381function TO_NUMBER() {
382 return %ToNumber(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000383}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000384
385
386// Convert the receiver to a string - forward to ToString.
387function TO_STRING() {
388 return %ToString(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000389}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000390
391
392/* -------------------------------------
393 - - - C o n v e r s i o n s - - -
394 -------------------------------------
395*/
396
397// ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
398// (1) for number hint, and (2) for string hint.
399function ToPrimitive(x, hint) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000400 // Fast case check.
401 if (IS_STRING(x)) return x;
402 // Normal behavior.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000403 if (!IS_OBJECT(x) && !IS_FUNCTION(x)) return x;
404 if (x == null) return x; // check for null, undefined
405 if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
406 return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000407}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000408
409
410// ECMA-262, section 9.3, page 31.
411function ToNumber(x) {
412 if (IS_NUMBER(x)) return x;
413 if (IS_STRING(x)) return %StringToNumber(x);
414 if (IS_BOOLEAN(x)) return x ? 1 : 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000415 if (IS_UNDEFINED(x)) return $NaN;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416 return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000417}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000418
419
420// ECMA-262, section 9.8, page 35.
421function ToString(x) {
422 if (IS_STRING(x)) return x;
423 if (IS_NUMBER(x)) return %NumberToString(x);
424 if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
425 if (IS_UNDEFINED(x)) return 'undefined';
426 return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000427}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000428
429
430// ... where did this come from?
431function ToBoolean(x) {
432 if (IS_BOOLEAN(x)) return x;
433 if (IS_STRING(x)) return x.length != 0;
434 if (x == null) return false;
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000435 if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000436 return true;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000437}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000438
439
440// ECMA-262, section 9.9, page 36.
441function ToObject(x) {
442 if (IS_STRING(x)) return new $String(x);
443 if (IS_NUMBER(x)) return new $Number(x);
444 if (IS_BOOLEAN(x)) return new $Boolean(x);
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000445 if (x == null) throw %MakeTypeError('null_to_object', []);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000446 return x;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000447}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000448
449
450// ECMA-262, section 9.4, page 34.
451function ToInteger(x) {
452 if (%_IsSmi(x)) return x;
453 return %NumberToInteger(ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000454}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000455
456
457// ECMA-262, section 9.6, page 34.
458function ToUint32(x) {
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000459 if (%_IsSmi(x) && x >= 0) return x;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000460 return %NumberToJSUint32(ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000461}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000462
463
464// ECMA-262, section 9.5, page 34
465function ToInt32(x) {
466 if (%_IsSmi(x)) return x;
467 return %NumberToJSInt32(ToNumber(x));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000468}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000469
470
471
472/* ---------------------------------
473 - - - U t i l i t i e s - - -
474 ---------------------------------
475*/
476
477// Returns if the given x is a primitive value - not an object or a
478// function.
479function IsPrimitive(x) {
480 if (!IS_OBJECT(x) && !IS_FUNCTION(x)) {
481 return true;
482 } else {
483 // Even though the type of null is "object", null is still
484 // considered a primitive value.
485 return IS_NULL(x);
486 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000487}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000488
489
490// ECMA-262, section 8.6.2.6, page 28.
491function DefaultNumber(x) {
492 if (IS_FUNCTION(x.valueOf)) {
493 var v = x.valueOf();
494 if (%IsPrimitive(v)) return v;
495 }
496
497 if (IS_FUNCTION(x.toString)) {
498 var s = x.toString();
499 if (%IsPrimitive(s)) return s;
500 }
501
502 throw %MakeTypeError('cannot_convert_to_primitive', []);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000503}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504
505
506// ECMA-262, section 8.6.2.6, page 28.
507function DefaultString(x) {
508 if (IS_FUNCTION(x.toString)) {
509 var s = x.toString();
510 if (%IsPrimitive(s)) return s;
511 }
512
513 if (IS_FUNCTION(x.valueOf)) {
514 var v = x.valueOf();
515 if (%IsPrimitive(v)) return v;
516 }
517
518 throw %MakeTypeError('cannot_convert_to_primitive', []);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000519}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000520
521
522// NOTE: Setting the prototype for Array must take place as early as
523// possible due to code generation for array literals. When
524// generating code for a array literal a boilerplate array is created
525// that is cloned when running the code. It is essiential that the
526// boilerplate gets the right prototype.
527%FunctionSetPrototype($Array, new $Array(0));