1 /* 2 * Copyright (C) 1999-2000 Harri Porten (porten (at) 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 29 namespace JSC { 30 31 ASSERT_CLASS_FITS_IN_CELL(ObjectPrototype); 32 33 static EncodedJSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState*); 34 static EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState*); 35 static EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState*); 36 static EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState*); 37 static EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState*); 38 static EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState*); 39 static EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*); 40 static EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*); 41 static EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*); 42 43 ObjectPrototype::ObjectPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* stucture, Structure* functionStructure) 44 : JSNonFinalObject(exec->globalData(), stucture) 45 , m_hasNoPropertiesWithUInt32Names(true) 46 { 47 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum); 48 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum); 49 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum); 50 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum); 51 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum); 52 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().isPrototypeOf, objectProtoFuncIsPrototypeOf), DontEnum); 53 54 // Mozilla extensions 55 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum); 56 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum); 57 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum); 58 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum); 59 } 60 61 void ObjectPrototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) 62 { 63 JSObject::put(exec, propertyName, value, slot); 64 65 if (m_hasNoPropertiesWithUInt32Names) { 66 bool isUInt32; 67 propertyName.toUInt32(isUInt32); 68 m_hasNoPropertiesWithUInt32Names = !isUInt32; 69 } 70 } 71 72 bool ObjectPrototype::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) 73 { 74 if (m_hasNoPropertiesWithUInt32Names) 75 return false; 76 return JSObject::getOwnPropertySlot(exec, propertyName, slot); 77 } 78 79 // ------------------------------ Functions -------------------------------- 80 81 // ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7 82 83 EncodedJSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec) 84 { 85 JSValue thisValue = exec->hostThisValue(); 86 return JSValue::encode(thisValue.toThisObject(exec)); 87 } 88 89 EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec) 90 { 91 JSValue thisValue = exec->hostThisValue(); 92 return JSValue::encode(jsBoolean(thisValue.toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, exec->argument(0).toString(exec))))); 93 } 94 95 EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec) 96 { 97 JSValue thisValue = exec->hostThisValue(); 98 JSObject* thisObj = thisValue.toThisObject(exec); 99 100 if (!exec->argument(0).isObject()) 101 return JSValue::encode(jsBoolean(false)); 102 103 JSValue v = asObject(exec->argument(0))->prototype(); 104 105 while (true) { 106 if (!v.isObject()) 107 return JSValue::encode(jsBoolean(false)); 108 if (v == thisObj) 109 return JSValue::encode(jsBoolean(true)); 110 v = asObject(v)->prototype(); 111 } 112 } 113 114 EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec) 115 { 116 JSValue thisValue = exec->hostThisValue(); 117 CallData callData; 118 if (getCallData(exec->argument(1), callData) == CallTypeNone) 119 return throwVMError(exec, createSyntaxError(exec, "invalid getter usage")); 120 thisValue.toThisObject(exec)->defineGetter(exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1))); 121 return JSValue::encode(jsUndefined()); 122 } 123 124 EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec) 125 { 126 JSValue thisValue = exec->hostThisValue(); 127 CallData callData; 128 if (getCallData(exec->argument(1), callData) == CallTypeNone) 129 return throwVMError(exec, createSyntaxError(exec, "invalid setter usage")); 130 thisValue.toThisObject(exec)->defineSetter(exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1))); 131 return JSValue::encode(jsUndefined()); 132 } 133 134 EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec) 135 { 136 JSValue thisValue = exec->hostThisValue(); 137 return JSValue::encode(thisValue.toThisObject(exec)->lookupGetter(exec, Identifier(exec, exec->argument(0).toString(exec)))); 138 } 139 140 EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec) 141 { 142 JSValue thisValue = exec->hostThisValue(); 143 return JSValue::encode(thisValue.toThisObject(exec)->lookupSetter(exec, Identifier(exec, exec->argument(0).toString(exec)))); 144 } 145 146 EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec) 147 { 148 JSValue thisValue = exec->hostThisValue(); 149 return JSValue::encode(jsBoolean(thisValue.toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, exec->argument(0).toString(exec))))); 150 } 151 152 EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec) 153 { 154 JSValue thisValue = exec->hostThisValue(); 155 return JSValue::encode(thisValue.toThisJSString(exec)); 156 } 157 158 EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec) 159 { 160 JSValue thisValue = exec->hostThisValue(); 161 return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisValue.toThisObject(exec)->className(), "]")); 162 } 163 164 } // namespace JSC 165