blob: 66a20eeeb451935549be853884d0a73e1a44ca46 [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
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000044
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000045// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046
47
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000048// Helper function used to install functions on objects.
49function InstallFunctions(object, attributes, functions) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000050 if (functions.length >= 8) {
51 %OptimizeObjectForAddingMultipleProperties(object, functions.length >> 1);
52 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000053 for (var i = 0; i < functions.length; i += 2) {
54 var key = functions[i];
55 var f = functions[i + 1];
56 %FunctionSetName(f, key);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +000057 %FunctionRemovePrototype(f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000058 %SetProperty(object, key, f, attributes);
59 }
ager@chromium.org5c838252010-02-19 08:53:10 +000060 %ToFastProperties(object);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000061}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000062
ager@chromium.org9085a012009-05-11 19:22:57 +000063// Emulates JSC by installing functions on a hidden prototype that
64// lies above the current object/prototype. This lets you override
65// functions on String.prototype etc. and then restore the old function
66// with delete. See http://code.google.com/p/chromium/issues/detail?id=1717
67function InstallFunctionsOnHiddenPrototype(object, attributes, functions) {
68 var hidden_prototype = new $Object();
69 %SetHiddenPrototype(object, hidden_prototype);
70 InstallFunctions(hidden_prototype, attributes, functions);
71}
72
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000073
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000074// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000075
76
77// ECMA 262 - 15.1.4
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000078function GlobalIsNaN(number) {
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +000079 var n = ToNumber(number);
80 return NUMBER_IS_NAN(n);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000081}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000082
83
84// ECMA 262 - 15.1.5
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000085function GlobalIsFinite(number) {
lrn@chromium.org25156de2010-04-06 13:10:27 +000086 if (!IS_NUMBER(number)) number = ToNumber(number);
87
88 // NaN - NaN == NaN, Infinity - Infinity == NaN, -Infinity - -Infinity == NaN.
89 return %_IsSmi(number) || number - number == 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000090}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000091
92
93// ECMA-262 - 15.1.2.2
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000094function GlobalParseInt(string, radix) {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000095 if (IS_UNDEFINED(radix)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000096 // Some people use parseInt instead of Math.floor. This
97 // optimization makes parseInt on a Smi 12 times faster (60ns
98 // vs 800ns). The following optimization makes parseInt on a
99 // non-Smi number 9 times faster (230ns vs 2070ns). Together
100 // they make parseInt on a string 1.4% slower (274ns vs 270ns).
101 if (%_IsSmi(string)) return string;
ager@chromium.org381abbb2009-02-25 13:23:22 +0000102 if (IS_NUMBER(string) &&
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000103 ((0.01 < string && string < 1e9) ||
104 (-1e9 < string && string < -0.01))) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000105 // Truncate number.
106 return string | 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000108 radix = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000109 } else {
110 radix = TO_INT32(radix);
111 if (!(radix == 0 || (2 <= radix && radix <= 36)))
112 return $NaN;
113 }
114 return %StringParseInt(ToString(string), radix);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000115}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000116
117
118// ECMA-262 - 15.1.2.3
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000119function GlobalParseFloat(string) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000120 return %StringParseFloat(ToString(string));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000121}
122
123
124function GlobalEval(x) {
125 if (!IS_STRING(x)) return x;
126
ager@chromium.orge2902be2009-06-08 12:21:35 +0000127 var global_receiver = %GlobalReceiver(global);
128 var this_is_global_receiver = (this === global_receiver);
129 var global_is_detached = (global === global_receiver);
130
131 if (!this_is_global_receiver || global_is_detached) {
132 throw new $EvalError('The "this" object passed to eval must ' +
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000133 'be the global object from which eval originated');
134 }
ager@chromium.orge2902be2009-06-08 12:21:35 +0000135
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000136 var f = %CompileString(x, false);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000137 if (!IS_FUNCTION(f)) return f;
138
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000139 return f.call(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000140}
141
142
143// execScript for IE compatibility.
144function GlobalExecScript(expr, lang) {
145 // NOTE: We don't care about the character casing.
146 if (!lang || /javascript/i.test(lang)) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000147 var f = %CompileString(ToString(expr), false);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000148 f.call(%GlobalReceiver(global));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000149 }
150 return null;
151}
152
153
154// ----------------------------------------------------------------------------
155
156
157function SetupGlobal() {
158 // ECMA 262 - 15.1.1.1.
159 %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
160
161 // ECMA-262 - 15.1.1.2.
162 %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE);
163
164 // ECMA-262 - 15.1.1.3.
165 %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000166
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000167 // Setup non-enumerable function on the global object.
168 InstallFunctions(global, DONT_ENUM, $Array(
169 "isNaN", GlobalIsNaN,
170 "isFinite", GlobalIsFinite,
171 "parseInt", GlobalParseInt,
172 "parseFloat", GlobalParseFloat,
173 "eval", GlobalEval,
174 "execScript", GlobalExecScript
175 ));
176}
177
178SetupGlobal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000179
180
181// ----------------------------------------------------------------------------
182// Boolean (first part of definition)
183
184
185%SetCode($Boolean, function(x) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000186 if (%_IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000187 %_SetValueOf(this, ToBoolean(x));
188 } else {
189 return ToBoolean(x);
190 }
191});
192
193%FunctionSetPrototype($Boolean, new $Boolean(false));
194
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000195%SetProperty($Boolean.prototype, "constructor", $Boolean, DONT_ENUM);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196
197// ----------------------------------------------------------------------------
198// Object
199
200$Object.prototype.constructor = $Object;
201
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000202// ECMA-262 - 15.2.4.2
203function ObjectToString() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000204 return "[object " + %_ClassOf(ToObject(this)) + "]";
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.3
209function ObjectToLocaleString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210 return this.toString();
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.4
215function ObjectValueOf() {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000216 return ToObject(this);
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.5
221function ObjectHasOwnProperty(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222 return %HasLocalProperty(ToObject(this), ToString(V));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000223}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000224
225
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000226// ECMA-262 - 15.2.4.6
227function ObjectIsPrototypeOf(V) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000228 if (!IS_OBJECT(V) && !IS_FUNCTION(V) && !IS_UNDETECTABLE(V)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229 return %IsInPrototypeChain(this, V);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000230}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231
232
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000233// ECMA-262 - 15.2.4.6
234function ObjectPropertyIsEnumerable(V) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000235 if (this == null) return false;
236 if (!IS_OBJECT(this) && !IS_FUNCTION(this)) return false;
237 return %IsPropertyEnumerable(this, ToString(V));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000238}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000239
240
241// Extensions for providing property getters and setters.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000242function ObjectDefineGetter(name, fun) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000243 if (this == null && !IS_UNDETECTABLE(this)) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000244 throw new $TypeError('Object.prototype.__defineGetter__: this is Null');
245 }
246 if (!IS_FUNCTION(fun)) {
247 throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
248 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249 return %DefineAccessor(ToObject(this), ToString(name), GETTER, fun);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000250}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251
252
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000253function ObjectLookupGetter(name) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000254 if (this == null && !IS_UNDETECTABLE(this)) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000255 throw new $TypeError('Object.prototype.__lookupGetter__: this is Null');
256 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000257 return %LookupAccessor(ToObject(this), ToString(name), GETTER);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000258}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000259
260
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000261function ObjectDefineSetter(name, fun) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000262 if (this == null && !IS_UNDETECTABLE(this)) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000263 throw new $TypeError('Object.prototype.__defineSetter__: this is Null');
264 }
265 if (!IS_FUNCTION(fun)) {
266 throw new $TypeError(
267 'Object.prototype.__defineSetter__: Expecting function');
268 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000269 return %DefineAccessor(ToObject(this), ToString(name), SETTER, fun);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000270}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000271
272
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000273function ObjectLookupSetter(name) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000274 if (this == null && !IS_UNDETECTABLE(this)) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000275 throw new $TypeError('Object.prototype.__lookupSetter__: this is Null');
276 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000277 return %LookupAccessor(ToObject(this), ToString(name), SETTER);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000278}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279
280
christian.plesner.hansen@gmail.com2bc58ef2009-09-22 10:00:30 +0000281function ObjectKeys(obj) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000282 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
283 !IS_UNDETECTABLE(obj))
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000284 throw MakeTypeError("obj_ctor_property_non_object", ["keys"]);
christian.plesner.hansen@gmail.com2bc58ef2009-09-22 10:00:30 +0000285 return %LocalKeys(obj);
286}
287
288
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000289// ES5 8.10.1.
290function IsAccessorDescriptor(desc) {
291 if (IS_UNDEFINED(desc)) return false;
292 return desc.hasGetter_ || desc.hasSetter_;
293}
294
295
296// ES5 8.10.2.
297function IsDataDescriptor(desc) {
298 if (IS_UNDEFINED(desc)) return false;
299 return desc.hasValue_ || desc.hasWritable_;
300}
301
302
303// ES5 8.10.3.
304function IsGenericDescriptor(desc) {
305 return !(IsAccessorDescriptor(desc) || IsDataDescriptor(desc));
306}
307
308
309function IsInconsistentDescriptor(desc) {
310 return IsAccessorDescriptor(desc) && IsDataDescriptor(desc);
311}
312
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000313// ES5 8.10.4
314function FromPropertyDescriptor(desc) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000315 if (IS_UNDEFINED(desc)) return desc;
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000316 var obj = new $Object();
317 if (IsDataDescriptor(desc)) {
318 obj.value = desc.getValue();
319 obj.writable = desc.isWritable();
320 }
321 if (IsAccessorDescriptor(desc)) {
322 obj.get = desc.getGet();
323 obj.set = desc.getSet();
324 }
325 obj.enumerable = desc.isEnumerable();
326 obj.configurable = desc.isConfigurable();
327 return obj;
328}
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000329
330// ES5 8.10.5.
331function ToPropertyDescriptor(obj) {
332 if (!IS_OBJECT(obj)) {
333 throw MakeTypeError("property_desc_object", [obj]);
334 }
335 var desc = new PropertyDescriptor();
336
337 if ("enumerable" in obj) {
338 desc.setEnumerable(ToBoolean(obj.enumerable));
339 }
340
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000341 if ("configurable" in obj) {
342 desc.setConfigurable(ToBoolean(obj.configurable));
343 }
344
345 if ("value" in obj) {
346 desc.setValue(obj.value);
347 }
348
349 if ("writable" in obj) {
350 desc.setWritable(ToBoolean(obj.writable));
351 }
352
353 if ("get" in obj) {
354 var get = obj.get;
355 if (!IS_UNDEFINED(get) && !IS_FUNCTION(get)) {
356 throw MakeTypeError("getter_must_be_callable", [get]);
357 }
358 desc.setGet(get);
359 }
360
361 if ("set" in obj) {
362 var set = obj.set;
363 if (!IS_UNDEFINED(set) && !IS_FUNCTION(set)) {
364 throw MakeTypeError("setter_must_be_callable", [set]);
365 }
366 desc.setSet(set);
367 }
368
369 if (IsInconsistentDescriptor(desc)) {
370 throw MakeTypeError("value_and_accessor", [obj]);
371 }
372 return desc;
373}
374
375
376function PropertyDescriptor() {
377 // Initialize here so they are all in-object and have the same map.
378 // Default values from ES5 8.6.1.
379 this.value_ = void 0;
380 this.hasValue_ = false;
381 this.writable_ = false;
382 this.hasWritable_ = false;
383 this.enumerable_ = false;
ager@chromium.org5c838252010-02-19 08:53:10 +0000384 this.hasEnumerable_ = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000385 this.configurable_ = false;
ager@chromium.org5c838252010-02-19 08:53:10 +0000386 this.hasConfigurable_ = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000387 this.get_ = void 0;
388 this.hasGetter_ = false;
389 this.set_ = void 0;
390 this.hasSetter_ = false;
391}
392
393
394PropertyDescriptor.prototype.setValue = function(value) {
395 this.value_ = value;
396 this.hasValue_ = true;
397}
398
399
400PropertyDescriptor.prototype.getValue = function() {
401 return this.value_;
402}
403
404
ager@chromium.org5c838252010-02-19 08:53:10 +0000405PropertyDescriptor.prototype.hasValue = function() {
406 return this.hasValue_;
407}
408
409
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000410PropertyDescriptor.prototype.setEnumerable = function(enumerable) {
411 this.enumerable_ = enumerable;
ager@chromium.org5c838252010-02-19 08:53:10 +0000412 this.hasEnumerable_ = true;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000413}
414
415
416PropertyDescriptor.prototype.isEnumerable = function () {
417 return this.enumerable_;
418}
419
420
ager@chromium.org5c838252010-02-19 08:53:10 +0000421PropertyDescriptor.prototype.hasEnumerable = function() {
422 return this.hasEnumerable_;
423}
424
425
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000426PropertyDescriptor.prototype.setWritable = function(writable) {
427 this.writable_ = writable;
428 this.hasWritable_ = true;
429}
430
431
432PropertyDescriptor.prototype.isWritable = function() {
433 return this.writable_;
434}
435
436
437PropertyDescriptor.prototype.setConfigurable = function(configurable) {
438 this.configurable_ = configurable;
ager@chromium.org5c838252010-02-19 08:53:10 +0000439 this.hasConfigurable_ = true;
440}
441
442
443PropertyDescriptor.prototype.hasConfigurable = function() {
444 return this.hasConfigurable_;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000445}
446
447
448PropertyDescriptor.prototype.isConfigurable = function() {
449 return this.configurable_;
450}
451
452
453PropertyDescriptor.prototype.setGet = function(get) {
454 this.get_ = get;
455 this.hasGetter_ = true;
456}
457
458
459PropertyDescriptor.prototype.getGet = function() {
460 return this.get_;
461}
462
463
ager@chromium.org5c838252010-02-19 08:53:10 +0000464PropertyDescriptor.prototype.hasGetter = function() {
465 return this.hasGetter_;
466}
467
468
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000469PropertyDescriptor.prototype.setSet = function(set) {
470 this.set_ = set;
471 this.hasSetter_ = true;
472}
473
474
475PropertyDescriptor.prototype.getSet = function() {
476 return this.set_;
477}
478
479
ager@chromium.org5c838252010-02-19 08:53:10 +0000480PropertyDescriptor.prototype.hasSetter = function() {
481 return this.hasSetter_;
482}
483
484
485
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000486// ES5 section 8.12.1.
487function GetOwnProperty(obj, p) {
488 var desc = new PropertyDescriptor();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000489
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000490 // An array with:
491 // obj is a data property [false, value, Writeable, Enumerable, Configurable]
492 // obj is an accessor [true, Get, Set, Enumerable, Configurable]
493 var props = %GetOwnProperty(ToObject(obj), ToString(p));
494
ager@chromium.org5c838252010-02-19 08:53:10 +0000495 if (IS_UNDEFINED(props)) return void 0;
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000496
497 // This is an accessor
498 if (props[0]) {
499 desc.setGet(props[1]);
500 desc.setSet(props[2]);
501 } else {
502 desc.setValue(props[1]);
503 desc.setWritable(props[2]);
504 }
505 desc.setEnumerable(props[3]);
506 desc.setConfigurable(props[4]);
507
508 return desc;
509}
510
511
ager@chromium.org5c838252010-02-19 08:53:10 +0000512// ES5 section 8.12.2.
513function GetProperty(obj, p) {
514 var prop = GetOwnProperty(obj);
515 if (!IS_UNDEFINED(prop)) return prop;
516 var proto = obj.__proto__;
517 if (IS_NULL(proto)) return void 0;
518 return GetProperty(proto, p);
519}
520
521
522// ES5 section 8.12.6
523function HasProperty(obj, p) {
524 var desc = GetProperty(obj, p);
525 return IS_UNDEFINED(desc) ? false : true;
526}
527
528
lrn@chromium.org25156de2010-04-06 13:10:27 +0000529// ES5 8.12.9.
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000530function DefineOwnProperty(obj, p, desc, should_throw) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000531 var current = GetOwnProperty(obj, p);
532 var extensible = %IsExtensible(ToObject(obj));
533
534 // Error handling according to spec.
535 // Step 3
536 if (IS_UNDEFINED(current) && !extensible)
537 throw MakeTypeError("define_disallowed", ["defineProperty"]);
538
539 if (!IS_UNDEFINED(current) && !current.isConfigurable()) {
540 // Step 7
541 if (desc.isConfigurable() || desc.isEnumerable() != current.isEnumerable())
542 throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
543 // Step 9
544 if (IsDataDescriptor(current) != IsDataDescriptor(desc))
545 throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
546 // Step 10
547 if (IsDataDescriptor(current) && IsDataDescriptor(desc)) {
548 if (!current.isWritable() && desc.isWritable())
549 throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
550 if (!current.isWritable() && desc.hasValue() &&
551 !SameValue(desc.getValue(), current.getValue())) {
552 throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
553 }
554 }
555 // Step 11
556 if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) {
557 if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())){
558 throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
559 }
560 if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet()))
561 throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
562 }
563 }
564
lrn@chromium.org25156de2010-04-06 13:10:27 +0000565 // Send flags - enumerable and configurable are common - writable is
ager@chromium.org5c838252010-02-19 08:53:10 +0000566 // only send to the data descriptor.
567 // Take special care if enumerable and configurable is not defined on
568 // desc (we need to preserve the existing values from current).
569 var flag = NONE;
570 if (desc.hasEnumerable()) {
571 flag |= desc.isEnumerable() ? 0 : DONT_ENUM;
572 } else if (!IS_UNDEFINED(current)) {
573 flag |= current.isEnumerable() ? 0 : DONT_ENUM;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000574 } else {
ager@chromium.org5c838252010-02-19 08:53:10 +0000575 flag |= DONT_ENUM;
576 }
577
578 if (desc.hasConfigurable()) {
579 flag |= desc.isConfigurable() ? 0 : DONT_DELETE;
580 } else if (!IS_UNDEFINED(current)) {
581 flag |= current.isConfigurable() ? 0 : DONT_DELETE;
582 } else
583 flag |= DONT_DELETE;
584
585 if (IsDataDescriptor(desc) || IsGenericDescriptor(desc)) {
586 flag |= desc.isWritable() ? 0 : READ_ONLY;
587 %DefineOrRedefineDataProperty(obj, p, desc.getValue(), flag);
588 } else {
589 if (desc.hasGetter() && IS_FUNCTION(desc.getGet())) {
590 %DefineOrRedefineAccessorProperty(obj, p, GETTER, desc.getGet(), flag);
591 }
592 if (desc.hasSetter() && IS_FUNCTION(desc.getSet())) {
593 %DefineOrRedefineAccessorProperty(obj, p, SETTER, desc.getSet(), flag);
594 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000595 }
596 return true;
597}
598
599
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000600// ES5 section 15.2.3.2.
601function ObjectGetPrototypeOf(obj) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000602 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
603 !IS_UNDETECTABLE(obj))
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000604 throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]);
605 return obj.__proto__;
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000606}
607
608
lrn@chromium.org25156de2010-04-06 13:10:27 +0000609// ES5 section 15.2.3.3
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000610function ObjectGetOwnPropertyDescriptor(obj, p) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000611 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
612 !IS_UNDETECTABLE(obj))
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000613 throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyDescriptor"]);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000614 var desc = GetOwnProperty(obj, p);
615 return FromPropertyDescriptor(desc);
616}
617
618
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000619// ES5 section 15.2.3.4.
620function ObjectGetOwnPropertyNames(obj) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000621 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
622 !IS_UNDETECTABLE(obj))
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000623 throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyNames"]);
624
625 // Find all the indexed properties.
626
627 // Get the local element names.
628 var propertyNames = %GetLocalElementNames(obj);
629
630 // Get names for indexed interceptor properties.
631 if (%GetInterceptorInfo(obj) & 1) {
632 var indexedInterceptorNames =
633 %GetIndexedInterceptorElementNames(obj);
ager@chromium.org5c838252010-02-19 08:53:10 +0000634 if (indexedInterceptorNames)
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000635 propertyNames = propertyNames.concat(indexedInterceptorNames);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000636 }
637
638 // Find all the named properties.
639
640 // Get the local property names.
641 propertyNames = propertyNames.concat(%GetLocalPropertyNames(obj));
642
643 // Get names for named interceptor properties if any.
644
645 if (%GetInterceptorInfo(obj) & 2) {
646 var namedInterceptorNames =
647 %GetNamedInterceptorPropertyNames(obj);
648 if (namedInterceptorNames) {
649 propertyNames = propertyNames.concat(namedInterceptorNames);
650 }
651 }
652
ager@chromium.org5c838252010-02-19 08:53:10 +0000653 // Property names are expected to be strings.
654 for (var i = 0; i < propertyNames.length; ++i)
655 propertyNames[i] = ToString(propertyNames[i]);
656
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000657 return propertyNames;
658}
659
660
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000661// ES5 section 15.2.3.5.
662function ObjectCreate(proto, properties) {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000663 // IS_OBJECT will return true on null covering that case.
664 if (!IS_OBJECT(proto) && !IS_FUNCTION(proto)) {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000665 throw MakeTypeError("proto_object_or_null", [proto]);
666 }
667 var obj = new $Object();
668 obj.__proto__ = proto;
669 if (!IS_UNDEFINED(properties)) ObjectDefineProperties(obj, properties);
670 return obj;
671}
672
673
ager@chromium.org5c838252010-02-19 08:53:10 +0000674// ES5 section 15.2.3.6.
675function ObjectDefineProperty(obj, p, attributes) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000676 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
677 !IS_UNDETECTABLE(obj))
ager@chromium.org5c838252010-02-19 08:53:10 +0000678 throw MakeTypeError("obj_ctor_property_non_object", ["defineProperty"]);
679 var name = ToString(p);
680 var desc = ToPropertyDescriptor(attributes);
681 DefineOwnProperty(obj, name, desc, true);
682 return obj;
683}
684
685
686// ES5 section 15.2.3.7.
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000687function ObjectDefineProperties(obj, properties) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000688 if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
689 !IS_UNDETECTABLE(obj))
ager@chromium.org5c838252010-02-19 08:53:10 +0000690 throw MakeTypeError("obj_ctor_property_non_object", ["defineProperties"]);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000691 var props = ToObject(properties);
692 var key_values = [];
693 for (var key in props) {
694 if (%HasLocalProperty(props, key)) {
695 key_values.push(key);
696 var value = props[key];
697 var desc = ToPropertyDescriptor(value);
698 key_values.push(desc);
699 }
700 }
701 for (var i = 0; i < key_values.length; i += 2) {
702 var key = key_values[i];
703 var desc = key_values[i + 1];
704 DefineOwnProperty(obj, key, desc, true);
705 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000706 return obj;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000707}
708
709
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000710%SetCode($Object, function(x) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000711 if (%_IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000712 if (x == null) return this;
713 return ToObject(x);
714 } else {
715 if (x == null) return { };
716 return ToObject(x);
717 }
718});
719
720
721// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000722
723
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000724function SetupObject() {
725 // Setup non-enumerable functions on the Object.prototype object.
726 InstallFunctions($Object.prototype, DONT_ENUM, $Array(
727 "toString", ObjectToString,
728 "toLocaleString", ObjectToLocaleString,
729 "valueOf", ObjectValueOf,
730 "hasOwnProperty", ObjectHasOwnProperty,
731 "isPrototypeOf", ObjectIsPrototypeOf,
732 "propertyIsEnumerable", ObjectPropertyIsEnumerable,
733 "__defineGetter__", ObjectDefineGetter,
734 "__lookupGetter__", ObjectLookupGetter,
735 "__defineSetter__", ObjectDefineSetter,
736 "__lookupSetter__", ObjectLookupSetter
737 ));
christian.plesner.hansen@gmail.com2bc58ef2009-09-22 10:00:30 +0000738 InstallFunctions($Object, DONT_ENUM, $Array(
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000739 "keys", ObjectKeys,
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000740 "create", ObjectCreate,
ager@chromium.org5c838252010-02-19 08:53:10 +0000741 "defineProperty", ObjectDefineProperty,
742 "defineProperties", ObjectDefineProperties,
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000743 "getPrototypeOf", ObjectGetPrototypeOf,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000744 "getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor,
745 "getOwnPropertyNames", ObjectGetOwnPropertyNames
christian.plesner.hansen@gmail.com2bc58ef2009-09-22 10:00:30 +0000746 ));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000747}
748
749SetupObject();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000750
751
752// ----------------------------------------------------------------------------
753// Boolean
754
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000755function BooleanToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000756 // NOTE: Both Boolean objects and values can enter here as
757 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000758 if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000759 throw new $TypeError('Boolean.prototype.toString is not generic');
760 return ToString(%_ValueOf(this));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000761}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762
763
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000764function BooleanValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000765 // NOTE: Both Boolean objects and values can enter here as
766 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000767 if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000768 throw new $TypeError('Boolean.prototype.valueOf is not generic');
769 return %_ValueOf(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000770}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000771
772
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000773function BooleanToJSON(key) {
774 return CheckJSONPrimitive(this.valueOf());
775}
776
777
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000778// ----------------------------------------------------------------------------
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000779
780
781function SetupBoolean() {
782 InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
783 "toString", BooleanToString,
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000784 "valueOf", BooleanValueOf,
785 "toJSON", BooleanToJSON
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000786 ));
787}
788
789SetupBoolean();
790
791// ----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000792// Number
793
794// Set the Number function and constructor.
795%SetCode($Number, function(x) {
796 var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000797 if (%_IsConstructCall()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000798 %_SetValueOf(this, value);
799 } else {
800 return value;
801 }
802});
803
804%FunctionSetPrototype($Number, new $Number(0));
805
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000806// ECMA-262 section 15.7.4.2.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000807function NumberToString(radix) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000808 // NOTE: Both Number objects and values can enter here as
809 // 'this'. This is not as dictated by ECMA-262.
810 var number = this;
811 if (!IS_NUMBER(this)) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000812 if (!IS_NUMBER_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000813 throw new $TypeError('Number.prototype.toString is not generic');
814 // Get the value of this number in case it's an object.
815 number = %_ValueOf(this);
816 }
817 // Fast case: Convert number in radix 10.
818 if (IS_UNDEFINED(radix) || radix === 10) {
819 return ToString(number);
820 }
821
822 // Convert the radix to an integer and check the range.
823 radix = TO_INTEGER(radix);
824 if (radix < 2 || radix > 36) {
825 throw new $RangeError('toString() radix argument must be between 2 and 36');
826 }
827 // Convert the number to a string in the given radix.
828 return %NumberToRadixString(number, radix);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000829}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000830
831
832// ECMA-262 section 15.7.4.3
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000833function NumberToLocaleString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000834 return this.toString();
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000835}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000836
837
838// ECMA-262 section 15.7.4.4
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000839function NumberValueOf() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000840 // NOTE: Both Number objects and values can enter here as
841 // 'this'. This is not as dictated by ECMA-262.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000842 if (!IS_NUMBER(this) && !IS_NUMBER_WRAPPER(this))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000843 throw new $TypeError('Number.prototype.valueOf is not generic');
844 return %_ValueOf(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000845}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000846
847
848// ECMA-262 section 15.7.4.5
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000849function NumberToFixed(fractionDigits) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000850 var f = TO_INTEGER(fractionDigits);
851 if (f < 0 || f > 20) {
852 throw new $RangeError("toFixed() digits argument must be between 0 and 20");
853 }
854 var x = ToNumber(this);
855 return %NumberToFixed(x, f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000856}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000857
858
859// ECMA-262 section 15.7.4.6
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000860function NumberToExponential(fractionDigits) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000861 var f = -1;
862 if (!IS_UNDEFINED(fractionDigits)) {
863 f = TO_INTEGER(fractionDigits);
864 if (f < 0 || f > 20) {
865 throw new $RangeError("toExponential() argument must be between 0 and 20");
866 }
867 }
868 var x = ToNumber(this);
869 return %NumberToExponential(x, f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000870}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871
872
873// ECMA-262 section 15.7.4.7
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000874function NumberToPrecision(precision) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875 if (IS_UNDEFINED(precision)) return ToString(%_ValueOf(this));
876 var p = TO_INTEGER(precision);
877 if (p < 1 || p > 21) {
878 throw new $RangeError("toPrecision() argument must be between 1 and 21");
879 }
880 var x = ToNumber(this);
881 return %NumberToPrecision(x, p);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000882}
883
884
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000885function CheckJSONPrimitive(val) {
886 if (!IsPrimitive(val))
887 throw MakeTypeError('result_not_primitive', ['toJSON', val]);
888 return val;
889}
890
891
892function NumberToJSON(key) {
893 return CheckJSONPrimitive(this.valueOf());
894}
895
896
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000897// ----------------------------------------------------------------------------
898
899function SetupNumber() {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000900 %OptimizeObjectForAddingMultipleProperties($Number.prototype, 8);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000901 // Setup the constructor property on the Number prototype object.
902 %SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
903
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000904 %OptimizeObjectForAddingMultipleProperties($Number, 5);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000905 // ECMA-262 section 15.7.3.1.
906 %SetProperty($Number,
907 "MAX_VALUE",
908 1.7976931348623157e+308,
909 DONT_ENUM | DONT_DELETE | READ_ONLY);
910
911 // ECMA-262 section 15.7.3.2.
912 %SetProperty($Number, "MIN_VALUE", 5e-324, DONT_ENUM | DONT_DELETE | READ_ONLY);
913
914 // ECMA-262 section 15.7.3.3.
915 %SetProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
916
917 // ECMA-262 section 15.7.3.4.
918 %SetProperty($Number,
919 "NEGATIVE_INFINITY",
920 -1/0,
921 DONT_ENUM | DONT_DELETE | READ_ONLY);
922
923 // ECMA-262 section 15.7.3.5.
924 %SetProperty($Number,
925 "POSITIVE_INFINITY",
926 1/0,
927 DONT_ENUM | DONT_DELETE | READ_ONLY);
ager@chromium.org5c838252010-02-19 08:53:10 +0000928 %ToFastProperties($Number);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000929
930 // Setup non-enumerable functions on the Number prototype object.
931 InstallFunctions($Number.prototype, DONT_ENUM, $Array(
932 "toString", NumberToString,
933 "toLocaleString", NumberToLocaleString,
934 "valueOf", NumberValueOf,
935 "toFixed", NumberToFixed,
936 "toExponential", NumberToExponential,
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000937 "toPrecision", NumberToPrecision,
938 "toJSON", NumberToJSON
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000939 ));
940}
941
942SetupNumber();
943
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000944
945
946// ----------------------------------------------------------------------------
947// Function
948
949$Function.prototype.constructor = $Function;
950
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000951function FunctionSourceString(func) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000952 if (!IS_FUNCTION(func)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000953 throw new $TypeError('Function.prototype.toString is not generic');
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000954 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000955
956 var source = %FunctionGetSourceCode(func);
christian.plesner.hansen@gmail.com2bc58ef2009-09-22 10:00:30 +0000957 if (!IS_STRING(source) || %FunctionIsBuiltin(func)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000958 var name = %FunctionGetName(func);
959 if (name) {
960 // Mimic what KJS does.
961 return 'function ' + name + '() { [native code] }';
962 } else {
963 return 'function () { [native code] }';
964 }
965 }
966
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000967 var name = %FunctionGetName(func);
968 return 'function ' + name + source;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000969}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000970
971
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000972function FunctionToString() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000973 return FunctionSourceString(this);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000974}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000975
976
977function NewFunction(arg1) { // length == 1
978 var n = %_ArgumentsLength();
979 var p = '';
980 if (n > 1) {
981 p = new $Array(n - 1);
982 // Explicitly convert all parameters to strings.
983 // Array.prototype.join replaces null with empty strings which is
984 // not appropriate.
985 for (var i = 0; i < n - 1; i++) p[i] = ToString(%_Arguments(i));
986 p = p.join(',');
987 // If the formal parameters string include ) - an illegal
988 // character - it may make the combined function expression
989 // compile. We avoid this problem by checking for this early on.
990 if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]);
991 }
992 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : '';
ager@chromium.org236ad962008-09-25 09:45:57 +0000993 var source = '(function(' + p + ') {\n' + body + '\n})';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000994
995 // The call to SetNewFunctionAttributes will ensure the prototype
996 // property of the resulting function is enumerable (ECMA262, 15.3.5.2).
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000997 var f = %CompileString(source, false)();
ager@chromium.org236ad962008-09-25 09:45:57 +0000998 %FunctionSetName(f, "anonymous");
999 return %SetNewFunctionAttributes(f);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001000}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001001
1002%SetCode($Function, NewFunction);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001003
1004// ----------------------------------------------------------------------------
1005
1006function SetupFunction() {
1007 InstallFunctions($Function.prototype, DONT_ENUM, $Array(
1008 "toString", FunctionToString
1009 ));
1010}
1011
1012SetupFunction();