1 /*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 #include "config.h"
22 #include "ObjectPrototype.h"
23
24 #include "Error.h"
25 #include "JSFunction.h"
26 #include "JSString.h"
27 #include "JSStringBuilder.h"
28 #include "PrototypeFunction.h"
29
30 namespace JSC {
31
32 ASSERT_CLASS_FITS_IN_CELL(ObjectPrototype);
33
34 static JSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState*, JSObject*, JSValue, const ArgList&);
35 static JSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState*, JSObject*, JSValue, const ArgList&);
36 static JSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&);
37 static JSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState*, JSObject*, JSValue, const ArgList&);
38 static JSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState*, JSObject*, JSValue, const ArgList&);
39 static JSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState*, JSObject*, JSValue, const ArgList&);
40 static JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*, JSObject*, JSValue, const ArgList&);
41 static JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue, const ArgList&);
42 static JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
43
ObjectPrototype(ExecState * exec,NonNullPassRefPtr<Structure> stucture,Structure * prototypeFunctionStructure)44 ObjectPrototype::ObjectPrototype(ExecState* exec, NonNullPassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure)
45 : JSObject(stucture)
46 , m_hasNoPropertiesWithUInt32Names(true)
47 {
48 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
49 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
50 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum);
51 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum);
52 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum);
53 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().isPrototypeOf, objectProtoFuncIsPrototypeOf), DontEnum);
54
55 // Mozilla extensions
56 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum);
57 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum);
58 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum);
59 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum);
60 }
61
put(ExecState * exec,const Identifier & propertyName,JSValue value,PutPropertySlot & slot)62 void ObjectPrototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
63 {
64 JSObject::put(exec, propertyName, value, slot);
65
66 if (m_hasNoPropertiesWithUInt32Names) {
67 bool isUInt32;
68 propertyName.toStrictUInt32(&isUInt32);
69 m_hasNoPropertiesWithUInt32Names = !isUInt32;
70 }
71 }
72
getOwnPropertySlot(ExecState * exec,unsigned propertyName,PropertySlot & slot)73 bool ObjectPrototype::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
74 {
75 if (m_hasNoPropertiesWithUInt32Names)
76 return false;
77 return JSObject::getOwnPropertySlot(exec, propertyName, slot);
78 }
79
80 // ------------------------------ Functions --------------------------------
81
82 // ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7
83
objectProtoFuncValueOf(ExecState * exec,JSObject *,JSValue thisValue,const ArgList &)84 JSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
85 {
86 return thisValue.toThisObject(exec);
87 }
88
objectProtoFuncHasOwnProperty(ExecState * exec,JSObject *,JSValue thisValue,const ArgList & args)89 JSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
90 {
91 return jsBoolean(thisValue.toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args.at(0).toString(exec))));
92 }
93
objectProtoFuncIsPrototypeOf(ExecState * exec,JSObject *,JSValue thisValue,const ArgList & args)94 JSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
95 {
96 JSObject* thisObj = thisValue.toThisObject(exec);
97
98 if (!args.at(0).isObject())
99 return jsBoolean(false);
100
101 JSValue v = asObject(args.at(0))->prototype();
102
103 while (true) {
104 if (!v.isObject())
105 return jsBoolean(false);
106 if (v == thisObj)
107 return jsBoolean(true);
108 v = asObject(v)->prototype();
109 }
110 }
111
objectProtoFuncDefineGetter(ExecState * exec,JSObject *,JSValue thisValue,const ArgList & args)112 JSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
113 {
114 CallData callData;
115 if (args.at(1).getCallData(callData) == CallTypeNone)
116 return throwError(exec, SyntaxError, "invalid getter usage");
117 thisValue.toThisObject(exec)->defineGetter(exec, Identifier(exec, args.at(0).toString(exec)), asObject(args.at(1)));
118 return jsUndefined();
119 }
120
objectProtoFuncDefineSetter(ExecState * exec,JSObject *,JSValue thisValue,const ArgList & args)121 JSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
122 {
123 CallData callData;
124 if (args.at(1).getCallData(callData) == CallTypeNone)
125 return throwError(exec, SyntaxError, "invalid setter usage");
126 thisValue.toThisObject(exec)->defineSetter(exec, Identifier(exec, args.at(0).toString(exec)), asObject(args.at(1)));
127 return jsUndefined();
128 }
129
objectProtoFuncLookupGetter(ExecState * exec,JSObject *,JSValue thisValue,const ArgList & args)130 JSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
131 {
132 return thisValue.toThisObject(exec)->lookupGetter(exec, Identifier(exec, args.at(0).toString(exec)));
133 }
134
objectProtoFuncLookupSetter(ExecState * exec,JSObject *,JSValue thisValue,const ArgList & args)135 JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
136 {
137 return thisValue.toThisObject(exec)->lookupSetter(exec, Identifier(exec, args.at(0).toString(exec)));
138 }
139
objectProtoFuncPropertyIsEnumerable(ExecState * exec,JSObject *,JSValue thisValue,const ArgList & args)140 JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
141 {
142 return jsBoolean(thisValue.toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args.at(0).toString(exec))));
143 }
144
objectProtoFuncToLocaleString(ExecState * exec,JSObject *,JSValue thisValue,const ArgList &)145 JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
146 {
147 return thisValue.toThisJSString(exec);
148 }
149
objectProtoFuncToString(ExecState * exec,JSObject *,JSValue thisValue,const ArgList &)150 JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
151 {
152 return jsMakeNontrivialString(exec, "[object ", thisValue.toThisObject(exec)->className(), "]");
153 }
154
155 } // namespace JSC
156