source: webkit/trunk/JavaScriptCore/API/JSCallbackObjectFunctions.h@ 39851

Last change on this file since 39851 was 39851, checked in by [email protected], 16 years ago

JavaScriptCore:

2009-01-12 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Make the JSImmediate interface private.

All manipulation of JS values should be through the JSValuePtr class, not by using JSImmediate
directly. The key missing methods on JSValuePtr are:

  • isCell() - check for values that are JSCell*s, and as such where asCell() may be used.
  • isInt32Fast() getInt32Fast() - fast check/access for integer immediates.
  • isUInt32Fast() getUInt32Fast() - ditto for unsigned integer immediates.

The JIT is allowed full access to JSImmediate, since it needs to be able to directly
manipulate JSValuePtrs. The Interpreter is provided access to perform operations directly
on JSValuePtrs through the new JSFastMath interface.

No performance impact.

  • API/JSCallbackObjectFunctions.h: (JSC::::toNumber):
  • API/JSValueRef.cpp: (JSValueIsEqual): (JSValueIsStrictEqual):
  • JavaScriptCore.exp:
  • bytecode/CodeBlock.h: (JSC::CodeBlock::isKnownNotImmediate):
  • bytecompiler/BytecodeGenerator.cpp: (JSC::keyForImmediateSwitch):
  • bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::JSValueHashTraits::constructDeletedValue): (JSC::BytecodeGenerator::JSValueHashTraits::isDeletedValue):
  • interpreter/Interpreter.cpp: (JSC::jsLess): (JSC::jsLessEq): (JSC::jsAdd): (JSC::jsIsObjectType): (JSC::cachePrototypeChain): (JSC::Interpreter::tryCachePutByID): (JSC::Interpreter::tryCacheGetByID): (JSC::Interpreter::privateExecute): (JSC::Interpreter::tryCTICachePutByID): (JSC::Interpreter::tryCTICacheGetByID): (JSC::Interpreter::cti_op_add): (JSC::Interpreter::cti_op_get_by_id_self_fail): (JSC::Interpreter::cti_op_get_by_id_proto_list): (JSC::Interpreter::cti_op_instanceof): (JSC::Interpreter::cti_op_mul): (JSC::Interpreter::cti_op_get_by_val): (JSC::Interpreter::cti_op_get_by_val_byte_array): (JSC::Interpreter::cti_op_sub): (JSC::Interpreter::cti_op_put_by_val): (JSC::Interpreter::cti_op_put_by_val_array): (JSC::Interpreter::cti_op_put_by_val_byte_array): (JSC::Interpreter::cti_op_negate): (JSC::Interpreter::cti_op_div): (JSC::Interpreter::cti_op_eq): (JSC::Interpreter::cti_op_lshift): (JSC::Interpreter::cti_op_bitand): (JSC::Interpreter::cti_op_rshift): (JSC::Interpreter::cti_op_bitnot): (JSC::Interpreter::cti_op_neq): (JSC::Interpreter::cti_op_urshift): (JSC::Interpreter::cti_op_call_eval): (JSC::Interpreter::cti_op_throw): (JSC::Interpreter::cti_op_is_undefined): (JSC::Interpreter::cti_op_stricteq): (JSC::Interpreter::cti_op_nstricteq): (JSC::Interpreter::cti_op_switch_imm): (JSC::Interpreter::cti_vm_throw):
  • interpreter/Interpreter.h: (JSC::Interpreter::isJSArray): (JSC::Interpreter::isJSString): (JSC::Interpreter::isJSByteArray):
  • jit/JIT.cpp: (JSC::JIT::compileOpStrictEq): (JSC::JIT::privateCompileMainPass):
  • jit/JIT.h: (JSC::JIT::isStrictEqCaseHandledInJITCode):
  • jit/JITArithmetic.cpp: (JSC::JIT::compileFastArith_op_rshift): (JSC::JIT::compileFastArith_op_bitand): (JSC::JIT::compileFastArith_op_mod):
  • jit/JITCall.cpp: (JSC::JIT::unlinkCall): (JSC::JIT::compileOpCall):
  • jit/JITInlineMethods.h: (JSC::JIT::getConstantOperandImmediateInt): (JSC::JIT::isOperandConstantImmediateInt):
  • parser/Nodes.cpp: (JSC::processClauseList):
  • runtime/ArrayPrototype.cpp: (JSC::arrayProtoFuncIndexOf): (JSC::arrayProtoFuncLastIndexOf):
  • runtime/BooleanPrototype.cpp: (JSC::booleanProtoFuncValueOf):
  • runtime/Collector.cpp: (JSC::Heap::protect): (JSC::Heap::unprotect): (JSC::Heap::heap):
  • runtime/JSByteArray.cpp: (JSC::JSByteArray::getOwnPropertySlot):
  • runtime/JSByteArray.h: (JSC::JSByteArray::getIndex):
  • runtime/JSCell.cpp:
  • runtime/JSCell.h: (JSC::JSValuePtr::isNumberCell): (JSC::JSValuePtr::asCell): (JSC::JSValuePtr::isNumber):
  • runtime/JSGlobalObjectFunctions.cpp: (JSC::globalFuncParseInt):
  • runtime/JSImmediate.h: (JSC::js0): (JSC::jsImpossibleValue): (JSC::JSValuePtr::toInt32): (JSC::JSValuePtr::toUInt32): (JSC::JSValuePtr::isCell): (JSC::JSValuePtr::isInt32Fast): (JSC::JSValuePtr::getInt32Fast): (JSC::JSValuePtr::isUInt32Fast): (JSC::JSValuePtr::getUInt32Fast): (JSC::JSValuePtr::makeInt32Fast): (JSC::JSValuePtr::areBothInt32Fast): (JSC::JSFastMath::canDoFastBitwiseOperations): (JSC::JSFastMath::equal): (JSC::JSFastMath::notEqual): (JSC::JSFastMath::andImmediateNumbers): (JSC::JSFastMath::xorImmediateNumbers): (JSC::JSFastMath::orImmediateNumbers): (JSC::JSFastMath::canDoFastRshift): (JSC::JSFastMath::canDoFastUrshift): (JSC::JSFastMath::rightShiftImmediateNumbers): (JSC::JSFastMath::canDoFastAdditiveOperations): (JSC::JSFastMath::addImmediateNumbers): (JSC::JSFastMath::subImmediateNumbers): (JSC::JSFastMath::incImmediateNumber): (JSC::JSFastMath::decImmediateNumber):
  • runtime/JSNumberCell.h: (JSC::JSValuePtr::asNumberCell): (JSC::jsNumber): (JSC::JSValuePtr::uncheckedGetNumber): (JSC::JSNumberCell::toInt32): (JSC::JSNumberCell::toUInt32): (JSC::JSValuePtr::toJSNumber): (JSC::JSValuePtr::getNumber): (JSC::JSValuePtr::numberToInt32): (JSC::JSValuePtr::numberToUInt32):
  • runtime/JSObject.h: (JSC::JSValuePtr::isObject): (JSC::JSValuePtr::get): (JSC::JSValuePtr::put):
  • runtime/JSValue.cpp: (JSC::JSValuePtr::toInteger): (JSC::JSValuePtr::toIntegerPreserveNaN):
  • runtime/JSValue.h:
  • runtime/Operations.cpp: (JSC::JSValuePtr::equalSlowCase): (JSC::JSValuePtr::strictEqualSlowCase):
  • runtime/Operations.h: (JSC::JSValuePtr::equal): (JSC::JSValuePtr::equalSlowCaseInline): (JSC::JSValuePtr::strictEqual): (JSC::JSValuePtr::strictEqualSlowCaseInline):
  • runtime/Protect.h: (JSC::gcProtect): (JSC::gcUnprotect):
  • runtime/StringPrototype.cpp: (JSC::stringProtoFuncCharAt): (JSC::stringProtoFuncCharCodeAt):
  • runtime/Structure.cpp: (JSC::Structure::createCachedPrototypeChain):

WebCore:

2009-01-12 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Deprecate JSValuePtr::getNumber() - two ways to get a number should be enough.

  • bindings/js/JSSQLTransactionCustom.cpp: (WebCore::JSSQLTransaction::executeSql):
  • bindings/objc/WebScriptObject.mm: (+[WebScriptObject _convertValueToObjcValue:originRootObject:rootObject:]):

WebKit/mac:

2009-01-12 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Deprecate JSValuePtr::getNumber() - two ways to get a number should be enough.

  • WebView/WebView.mm: (aeDescFromJSValue):
  • Property svn:eol-style set to native
File size: 19.9 KB
Line 
1/*
2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Eric Seidel <[email protected]>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "APICast.h"
28#include "Error.h"
29#include "JSCallbackFunction.h"
30#include "JSClassRef.h"
31#include "JSGlobalObject.h"
32#include "JSLock.h"
33#include "JSObjectRef.h"
34#include "JSString.h"
35#include "JSStringRef.h"
36#include "OpaqueJSString.h"
37#include "PropertyNameArray.h"
38#include <wtf/Vector.h>
39
40namespace JSC {
41
42template <class Base>
43inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValuePtr value)
44{
45 ASSERT(asObject(value)->inherits(&info));
46 return static_cast<JSCallbackObject*>(asObject(value));
47}
48
49template <class Base>
50JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, PassRefPtr<Structure> structure, JSClassRef jsClass, void* data)
51 : Base(structure)
52 , m_callbackObjectData(new JSCallbackObjectData(data, jsClass))
53{
54 init(exec);
55}
56
57// Global object constructor.
58// FIXME: Move this into a separate JSGlobalCallbackObject class derived from this one.
59template <class Base>
60JSCallbackObject<Base>::JSCallbackObject(JSClassRef jsClass)
61 : Base()
62 , m_callbackObjectData(new JSCallbackObjectData(0, jsClass))
63{
64 ASSERT(Base::isGlobalObject());
65 init(static_cast<JSGlobalObject*>(this)->globalExec());
66}
67
68template <class Base>
69void JSCallbackObject<Base>::init(ExecState* exec)
70{
71 ASSERT(exec);
72
73 Vector<JSObjectInitializeCallback, 16> initRoutines;
74 JSClassRef jsClass = classRef();
75 do {
76 if (JSObjectInitializeCallback initialize = jsClass->initialize)
77 initRoutines.append(initialize);
78 } while ((jsClass = jsClass->parentClass));
79
80 // initialize from base to derived
81 for (int i = static_cast<int>(initRoutines.size()) - 1; i >= 0; i--) {
82 JSLock::DropAllLocks dropAllLocks(exec);
83 JSObjectInitializeCallback initialize = initRoutines[i];
84 initialize(toRef(exec), toRef(this));
85 }
86}
87
88template <class Base>
89JSCallbackObject<Base>::~JSCallbackObject()
90{
91 JSObjectRef thisRef = toRef(this);
92
93 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
94 if (JSObjectFinalizeCallback finalize = jsClass->finalize)
95 finalize(thisRef);
96}
97
98template <class Base>
99UString JSCallbackObject<Base>::className() const
100{
101 UString thisClassName = classRef()->className();
102 if (!thisClassName.isNull())
103 return thisClassName;
104
105 return Base::className();
106}
107
108template <class Base>
109bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
110{
111 JSContextRef ctx = toRef(exec);
112 JSObjectRef thisRef = toRef(this);
113 RefPtr<OpaqueJSString> propertyNameRef;
114
115 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
116 // optional optimization to bypass getProperty in cases when we only need to know if the property exists
117 if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
118 if (!propertyNameRef)
119 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
120 JSLock::DropAllLocks dropAllLocks(exec);
121 if (hasProperty(ctx, thisRef, propertyNameRef.get())) {
122 slot.setCustom(this, callbackGetter);
123 return true;
124 }
125 } else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
126 if (!propertyNameRef)
127 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
128 JSLock::DropAllLocks dropAllLocks(exec);
129 if (JSValueRef value = getProperty(ctx, thisRef, propertyNameRef.get(), toRef(exec->exceptionSlot()))) {
130 slot.setValue(toJS(value));
131 return true;
132 }
133 }
134
135 if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
136 if (staticValues->contains(propertyName.ustring().rep())) {
137 slot.setCustom(this, staticValueGetter);
138 return true;
139 }
140 }
141
142 if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
143 if (staticFunctions->contains(propertyName.ustring().rep())) {
144 slot.setCustom(this, staticFunctionGetter);
145 return true;
146 }
147 }
148 }
149
150 return Base::getOwnPropertySlot(exec, propertyName, slot);
151}
152
153template <class Base>
154bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
155{
156 return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
157}
158
159template <class Base>
160void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
161{
162 JSContextRef ctx = toRef(exec);
163 JSObjectRef thisRef = toRef(this);
164 RefPtr<OpaqueJSString> propertyNameRef;
165 JSValueRef valueRef = toRef(value);
166
167 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
168 if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
169 if (!propertyNameRef)
170 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
171 JSLock::DropAllLocks dropAllLocks(exec);
172 if (setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, toRef(exec->exceptionSlot())))
173 return;
174 }
175
176 if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
177 if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
178 if (entry->attributes & kJSPropertyAttributeReadOnly)
179 return;
180 if (JSObjectSetPropertyCallback setProperty = entry->setProperty) {
181 if (!propertyNameRef)
182 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
183 JSLock::DropAllLocks dropAllLocks(exec);
184 if (setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, toRef(exec->exceptionSlot())))
185 return;
186 } else
187 throwError(exec, ReferenceError, "Attempt to set a property that is not settable.");
188 }
189 }
190
191 if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
192 if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
193 if (entry->attributes & kJSPropertyAttributeReadOnly)
194 return;
195 JSCallbackObject<Base>::putDirect(propertyName, value); // put as override property
196 return;
197 }
198 }
199 }
200
201 return Base::put(exec, propertyName, value, slot);
202}
203
204template <class Base>
205bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& propertyName)
206{
207 JSContextRef ctx = toRef(exec);
208 JSObjectRef thisRef = toRef(this);
209 RefPtr<OpaqueJSString> propertyNameRef;
210
211 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
212 if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
213 if (!propertyNameRef)
214 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
215 JSLock::DropAllLocks dropAllLocks(exec);
216 if (deleteProperty(ctx, thisRef, propertyNameRef.get(), toRef(exec->exceptionSlot())))
217 return true;
218 }
219
220 if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
221 if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
222 if (entry->attributes & kJSPropertyAttributeDontDelete)
223 return false;
224 return true;
225 }
226 }
227
228 if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
229 if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
230 if (entry->attributes & kJSPropertyAttributeDontDelete)
231 return false;
232 return true;
233 }
234 }
235 }
236
237 return Base::deleteProperty(exec, propertyName);
238}
239
240template <class Base>
241bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, unsigned propertyName)
242{
243 return deleteProperty(exec, Identifier::from(exec, propertyName));
244}
245
246template <class Base>
247ConstructType JSCallbackObject<Base>::getConstructData(ConstructData& constructData)
248{
249 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
250 if (jsClass->callAsConstructor) {
251 constructData.native.function = construct;
252 return ConstructTypeHost;
253 }
254 }
255 return ConstructTypeNone;
256}
257
258template <class Base>
259JSObject* JSCallbackObject<Base>::construct(ExecState* exec, JSObject* constructor, const ArgList& args)
260{
261 JSContextRef execRef = toRef(exec);
262 JSObjectRef constructorRef = toRef(constructor);
263
264 for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(constructor)->classRef(); jsClass; jsClass = jsClass->parentClass) {
265 if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) {
266 int argumentCount = static_cast<int>(args.size());
267 Vector<JSValueRef, 16> arguments(argumentCount);
268 for (int i = 0; i < argumentCount; i++)
269 arguments[i] = toRef(args.at(exec, i));
270 JSLock::DropAllLocks dropAllLocks(exec);
271 return toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
272 }
273 }
274
275 ASSERT_NOT_REACHED(); // getConstructData should prevent us from reaching here
276 return 0;
277}
278
279template <class Base>
280bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr)
281{
282 JSContextRef execRef = toRef(exec);
283 JSObjectRef thisRef = toRef(this);
284
285 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
286 if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance) {
287 JSLock::DropAllLocks dropAllLocks(exec);
288 return hasInstance(execRef, thisRef, toRef(value), toRef(exec->exceptionSlot()));
289 }
290 }
291 return false;
292}
293
294template <class Base>
295CallType JSCallbackObject<Base>::getCallData(CallData& callData)
296{
297 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
298 if (jsClass->callAsFunction) {
299 callData.native.function = call;
300 return CallTypeHost;
301 }
302 }
303 return CallTypeNone;
304}
305
306template <class Base>
307JSValuePtr JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, JSValuePtr thisValue, const ArgList& args)
308{
309 JSContextRef execRef = toRef(exec);
310 JSObjectRef functionRef = toRef(functionObject);
311 JSObjectRef thisObjRef = toRef(thisValue->toThisObject(exec));
312
313 for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(functionObject)->classRef(); jsClass; jsClass = jsClass->parentClass) {
314 if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) {
315 int argumentCount = static_cast<int>(args.size());
316 Vector<JSValueRef, 16> arguments(argumentCount);
317 for (int i = 0; i < argumentCount; i++)
318 arguments[i] = toRef(args.at(exec, i));
319 JSLock::DropAllLocks dropAllLocks(exec);
320 return toJS(callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
321 }
322 }
323
324 ASSERT_NOT_REACHED(); // getCallData should prevent us from reaching here
325 return noValue();
326}
327
328template <class Base>
329void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
330{
331 JSContextRef execRef = toRef(exec);
332 JSObjectRef thisRef = toRef(this);
333
334 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
335 if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) {
336 JSLock::DropAllLocks dropAllLocks(exec);
337 getPropertyNames(execRef, thisRef, toRef(&propertyNames));
338 }
339
340 if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
341 typedef OpaqueJSClassStaticValuesTable::const_iterator iterator;
342 iterator end = staticValues->end();
343 for (iterator it = staticValues->begin(); it != end; ++it) {
344 UString::Rep* name = it->first.get();
345 StaticValueEntry* entry = it->second;
346 if (entry->getProperty && !(entry->attributes & kJSPropertyAttributeDontEnum))
347 propertyNames.add(Identifier(exec, name));
348 }
349 }
350
351 if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
352 typedef OpaqueJSClassStaticFunctionsTable::const_iterator iterator;
353 iterator end = staticFunctions->end();
354 for (iterator it = staticFunctions->begin(); it != end; ++it) {
355 UString::Rep* name = it->first.get();
356 StaticFunctionEntry* entry = it->second;
357 if (!(entry->attributes & kJSPropertyAttributeDontEnum))
358 propertyNames.add(Identifier(exec, name));
359 }
360 }
361 }
362
363 Base::getPropertyNames(exec, propertyNames);
364}
365
366template <class Base>
367double JSCallbackObject<Base>::toNumber(ExecState* exec) const
368{
369 // We need this check to guard against the case where this object is rhs of
370 // a binary expression where lhs threw an exception in its conversion to
371 // primitive
372 if (exec->hadException())
373 return NaN;
374 JSContextRef ctx = toRef(exec);
375 JSObjectRef thisRef = toRef(this);
376
377 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
378 if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
379 JSLock::DropAllLocks dropAllLocks(exec);
380 if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeNumber, toRef(exec->exceptionSlot()))) {
381 double dValue;
382 return toJS(value)->getNumber(dValue) ? dValue : NaN;
383 }
384 }
385
386 return Base::toNumber(exec);
387}
388
389template <class Base>
390UString JSCallbackObject<Base>::toString(ExecState* exec) const
391{
392 JSContextRef ctx = toRef(exec);
393 JSObjectRef thisRef = toRef(this);
394
395 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
396 if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
397 JSValueRef value;
398 {
399 JSLock::DropAllLocks dropAllLocks(exec);
400 value = convertToType(ctx, thisRef, kJSTypeString, toRef(exec->exceptionSlot()));
401 }
402 if (value)
403 return toJS(value)->getString();
404 }
405
406 return Base::toString(exec);
407}
408
409template <class Base>
410void JSCallbackObject<Base>::setPrivate(void* data)
411{
412 m_callbackObjectData->privateData = data;
413}
414
415template <class Base>
416void* JSCallbackObject<Base>::getPrivate()
417{
418 return m_callbackObjectData->privateData;
419}
420
421template <class Base>
422bool JSCallbackObject<Base>::inherits(JSClassRef c) const
423{
424 for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
425 if (jsClass == c)
426 return true;
427
428 return false;
429}
430
431template <class Base>
432JSValuePtr JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
433{
434 JSCallbackObject* thisObj = asCallbackObject(slot.slotBase());
435
436 JSObjectRef thisRef = toRef(thisObj);
437 RefPtr<OpaqueJSString> propertyNameRef;
438
439 for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass)
440 if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec))
441 if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep()))
442 if (JSObjectGetPropertyCallback getProperty = entry->getProperty) {
443 if (!propertyNameRef)
444 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
445 JSLock::DropAllLocks dropAllLocks(exec);
446 if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), toRef(exec->exceptionSlot())))
447 return toJS(value);
448 }
449
450 return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback.");
451}
452
453template <class Base>
454JSValuePtr JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
455{
456 JSCallbackObject* thisObj = asCallbackObject(slot.slotBase());
457
458 // Check for cached or override property.
459 PropertySlot slot2(thisObj);
460 if (thisObj->Base::getOwnPropertySlot(exec, propertyName, slot2))
461 return slot2.getValue(exec, propertyName);
462
463 for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) {
464 if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
465 if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
466 if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) {
467 JSObject* o = new (exec) JSCallbackFunction(exec, callAsFunction, propertyName);
468 thisObj->putDirect(propertyName, o, entry->attributes);
469 return o;
470 }
471 }
472 }
473 }
474
475 return throwError(exec, ReferenceError, "Static function property defined with NULL callAsFunction callback.");
476}
477
478template <class Base>
479JSValuePtr JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
480{
481 JSCallbackObject* thisObj = asCallbackObject(slot.slotBase());
482
483 JSObjectRef thisRef = toRef(thisObj);
484 RefPtr<OpaqueJSString> propertyNameRef;
485
486 for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass)
487 if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
488 if (!propertyNameRef)
489 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
490 JSLock::DropAllLocks dropAllLocks(exec);
491 if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), toRef(exec->exceptionSlot())))
492 return toJS(value);
493 }
494
495 return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist.");
496}
497
498} // namespace JSC
Note: See TracBrowser for help on using the repository browser.