Merge remote-tracking branch 'redux/master' into sh4-pool
[tamarin-stm.git] / core / ObjectClass.cpp
blob45c4e1d08fdd661d7de698a14f466f282074b24b
1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2006
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Adobe AS3 Team
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 #include "avmplus.h"
42 #include "BuiltinNatives.h"
44 namespace avmplus
46 ObjectClass::ObjectClass(VTable* cvtable)
47 : ClassClosure(cvtable)
49 toplevel()->objectClass = this;
51 // patch Object's instance vtable scope, since we created it earlier for
52 // bootstrapping
53 //ivtable()->scope = cvtable->scope;
55 AvmAssert(traits()->getSizeOfInstance() == sizeof(ObjectClass));
56 // it is correct call construct() when this.prototype == null
57 setPrototypePtr(construct());
60 void ObjectClass::initPrototype()
62 // patch global.__proto__ = Object.prototype
63 Toplevel* toplevel = this->toplevel();
64 toplevel->global()->setDelegate(prototypePtr()); // global.__proto__ = Object.prototype
65 this->setDelegate(toplevel->classClass()->prototypePtr()); // Object.__proto__ = Class.prototype
68 ScriptObject* ObjectClass::construct()
70 return (ScriptObject*) core()->newObject(ivtable(), prototypePtr());
73 // this = argv[0]
74 // arg1 = argv[1]
75 // argN = argv[argc]
76 Atom ObjectClass::call(int argc, Atom* argv)
78 // see E-262 15.2.1
79 if (argc == 0 || AvmCore::isNullOrUndefined(argv[1]))
80 return construct(argc, argv);
81 else
82 return argv[1];
85 // this = argv[0] (ignored)
86 // arg1 = argv[1]
87 // argN = argv[argc]
88 Atom ObjectClass::construct(int argc, Atom* argv)
90 switch (argc)
92 default:
93 // TODO throw exception if argc > 1 (see E4 semantics)
94 case 1: {
95 Atom o = argv[1];
96 if (!AvmCore::isNullOrUndefined(o))
97 return o;
98 // else fall through
100 case 0:
101 return construct()->atom();
106 15.2.4.5 Object.prototype.hasOwnProperty (V)
107 When the hasOwnProperty method is called with argument V, the following steps are taken:
108 1. Let O be this object.
109 2. Call ToString(V).
110 3. If O doesn't have a property with the name given by Result(2), return false.
111 4. Return true.
112 NOTE Unlike [[HasProperty]] (section 8.6.2.4), this method does not consider objects in the prototype chain.
114 bool ObjectClass::_hasOwnProperty(Atom thisAtom, Stringp name)
116 AvmCore* core = this->core();
117 name = name ? core->internString(name) : (Stringp)core->knull;
119 Traitsp t = NULL;
120 switch (atomKind(thisAtom))
122 case kObjectType:
124 // ISSUE should this look in traits and dynamic vars, or just dynamic vars.
125 ScriptObject* obj = AvmCore::atomToScriptObject(thisAtom);
126 // TODO
127 // The change below is important as otherwise we will throw error in a call to hasAtomProperty for ByteArrayObject.
128 // This gets us back to the behaviour which we had in Marlin.
129 // A bugzilla bug [ 562224 ] has been created to address this issue more cleanly in near future
130 return obj->traits()->getTraitsBindings()->findBinding(name, core->findPublicNamespace()) != BIND_NONE ||
131 obj->hasStringProperty(name);
133 case kNamespaceType:
134 case kStringType:
135 case kBooleanType:
136 case kDoubleType:
137 case kIntptrType:
138 t = toplevel()->toTraits(thisAtom);
139 break;
140 default:
141 return false;
143 // NOTE use caller's public namespace
144 return t->getTraitsBindings()->findBinding(name, core->findPublicNamespace()) != BIND_NONE;
147 bool ObjectClass::_propertyIsEnumerable(Atom thisAtom, Stringp name)
149 AvmCore* core = this->core();
150 name = name ? core->internString(name) : (Stringp)core->knull;
152 if (atomKind(thisAtom) == kObjectType)
154 ScriptObject* obj = AvmCore::atomToScriptObject(thisAtom);
155 return obj->getStringPropertyIsEnumerable(name);
157 else if (atomKind(thisAtom) == kNamespaceType)
159 // Special case:
160 // E4X 13.2.5.1, 13.2.5.2 specifies that prefix and uri
161 // are not DontEnum.
162 return name == core->kuri || name == core->kprefix;
164 else
166 return false;
170 void ObjectClass::_setPropertyIsEnumerable(Atom thisAtom, Stringp name, bool enumerable)
172 AvmCore* core = this->core();
173 name = name ? core->internString(name) : (Stringp)core->knull;
175 if (atomKind(thisAtom) == kObjectType)
177 ScriptObject* obj = AvmCore::atomToScriptObject(thisAtom);
178 obj->setStringPropertyIsEnumerable(name, enumerable);
180 else
182 // cannot create properties on a sealed object.
183 // NOTE just use the unmarked version
184 Multiname multiname(core->getAnyPublicNamespace(), name);
185 // NOTE use default public
186 toplevel()->throwReferenceError(kWriteSealedError, &multiname, traits());
191 15.2.4.6 Object.prototype.isPrototypeOf (V)
192 When the isPrototypeOf method is called with argument V, the following steps are taken:
193 1. Let O be this object.
194 2. If V is not an object, return false.
195 3. Let V be the value of the [[Prototype]] property of V.
196 4. if V is null, return false
197 5. If O and V refer to the same object or if they refer to objects joined to each other (section 13.1.2), return true.
198 6. Go to step 3.
200 bool ObjectClass::_isPrototypeOf(Atom thisAtom, Atom V)
202 // ECMA-262 Section 15.2.4.6
203 if (AvmCore::isNullOrUndefined(V))
204 return false;
206 ScriptObject* o = toplevel()->toPrototype(V);
207 for (; o != NULL; o = o->getDelegate())
209 if (o->atom() == thisAtom)
210 return true;
212 return false;
216 * Object.prototype.toString()
218 Stringp ObjectClass::_toString(Atom thisAtom)
220 AvmCore* core = this->core();
222 if (AvmCore::isObject(thisAtom))
224 return AvmCore::atomToScriptObject(thisAtom)->implToString();
226 else
228 Traits* t = toplevel()->toTraits(thisAtom);
229 Stringp s = core->concatStrings(core->newConstantStringLatin1("[object "), t->name());
230 return core->concatStrings(s, core->newConstantStringLatin1("]"));