source: webkit/trunk/JavaScriptCore/API/JSCallbackObject.cpp@ 17372

Last change on this file since 17372 was 17372, checked in by darin, 19 years ago

Reviewed by Geoff.

  • made changes so the code compiles with the highest warning level under MSVC (disabling some warnings, making some code fixes)
  • API/JSCallbackConstructor.cpp: (KJS::JSCallbackConstructor::construct):
  • API/JSCallbackFunction.cpp: (KJS::JSCallbackFunction::callAsFunction):
  • API/JSCallbackObject.cpp: (KJS::JSCallbackObject::init): (KJS::JSCallbackObject::construct): (KJS::JSCallbackObject::callAsFunction):
  • API/JSObjectRef.cpp: (JSPropertyNameArrayGetNameAtIndex):
  • API/JSStringRef.cpp: (JSStringCreateWithCharacters):
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • bindings/c/c_utility.cpp: (KJS::Bindings::convertUTF8ToUTF16): (KJS::Bindings::coerceValueToNPVariantStringType): (KJS::Bindings::convertValueToNPVariant):
  • kjs/DateMath.h: (KJS::GregorianDateTime::GregorianDateTime):
  • kjs/ExecState.h: (KJS::ExecState::hadException):
  • kjs/JSImmediate.h: (KJS::JSImmediate::fromDouble): (KJS::JSImmediate::toDouble): (KJS::JSImmediate::NanAsBits): (KJS::JSImmediate::oneAsBits):
  • kjs/Parser.h:
  • kjs/PropertyNameArray.h: (KJS::PropertyNameArray::size):
  • kjs/array_object.cpp: (ArrayObjectImp::callAsFunction):
  • kjs/bool_object.cpp: (BooleanObjectImp::callAsFunction):
  • kjs/collector.cpp: (KJS::Collector::allocate): (KJS::Collector::markCurrentThreadConservatively): (KJS::Collector::collect):
  • kjs/completion.h: (KJS::Completion::isValueCompletion):
  • kjs/date_object.cpp: (KJS::findMonth):
  • kjs/debugger.cpp: (Debugger::sourceParsed): (Debugger::sourceUnused): (Debugger::exception): (Debugger::atStatement): (Debugger::callEvent): (Debugger::returnEvent):
  • kjs/dtoa.cpp:
  • kjs/error_object.cpp: (ErrorObjectImp::callAsFunction): (NativeErrorImp::callAsFunction):
  • kjs/function.cpp: (KJS::FunctionImp::processVarDecls): (KJS::GlobalFuncImp::callAsFunction):
  • kjs/function_object.cpp: (FunctionPrototype::callAsFunction):
  • kjs/grammar.y:
  • kjs/identifier.cpp: (KJS::CStringTranslator::translate): (KJS::Identifier::add):
  • kjs/internal.h:
  • kjs/lexer.cpp: (Lexer::lex): (Lexer::isIdentStart): (Lexer::isIdentPart): (isDecimalDigit): (Lexer::isHexDigit): (Lexer::isOctalDigit): (Lexer::matchPunctuator): (Lexer::singleEscape): (Lexer::convertOctal): (Lexer::convertHex): (Lexer::convertUnicode): (Lexer::record8):
  • kjs/lexer.h:
  • kjs/math_object.cpp: (MathFuncImp::callAsFunction):
  • kjs/number_object.cpp: (integer_part_noexp): (intPow10): (NumberProtoFunc::callAsFunction): (NumberObjectImp::callAsFunction):
  • kjs/object.cpp: (KJS::JSObject::deleteProperty): (KJS::JSObject::callAsFunction): (KJS::JSObject::toBoolean): (KJS::JSObject::toObject):
  • kjs/object.h: (KJS::JSObject::getPropertySlot):
  • kjs/property_map.cpp: (KJS::isValid): (KJS::PropertyMap::put): (KJS::PropertyMap::insert): (KJS::PropertyMap::containsGettersOrSetters):
  • kjs/property_map.h: (KJS::PropertyMap::hasGetterSetterProperties):
  • kjs/property_slot.h:
  • kjs/string_object.cpp: (StringInstance::getPropertyNames): (StringObjectImp::callAsFunction): (StringObjectFuncImp::callAsFunction):
  • kjs/ustring.cpp: (KJS::UString::Rep::computeHash): (KJS::UString::UString): (KJS::UString::from): (KJS::UString::append): (KJS::UString::ascii): (KJS::UString::operator=): (KJS::UString::find): (KJS::UString::rfind):
  • kjs/ustring.h: (KJS::UChar::high): (KJS::UChar::low): (KJS::UCharReference::low): (KJS::UCharReference::high):
  • kjs/value.cpp: (KJS::JSValue::toUInt16):
  • kjs/value.h:
  • pcre/pcre_compile.c: (get_othercase_range):
  • pcre/pcre_exec.c: (match):
  • pcre/pcre_internal.h:
  • wtf/HashFunctions.h: (WTF::intHash): (WTF::PtrHash::hash):
  • wtf/MathExtras.h: (isnan): (lround): (lroundf):
  • wtf/StringExtras.h: (strncasecmp):
  • wtf/unicode/icu/UnicodeIcu.h: (WTF::Unicode::isPrintableChar):
File size: 17.0 KB
Line 
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
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 <wtf/Platform.h>
28#include "JSCallbackObject.h"
29
30#include "APICast.h"
31#include "JSCallbackFunction.h"
32#include "JSClassRef.h"
33#include "JSObjectRef.h"
34#include "JSStringRef.h"
35#include "PropertyNameArray.h"
36#include "internal.h"
37#include <wtf/Vector.h>
38
39namespace KJS {
40
41const ClassInfo JSCallbackObject::info = { "CallbackObject", 0, 0, 0 };
42
43JSCallbackObject::JSCallbackObject(ExecState* exec, JSClassRef jsClass, JSValue* prototype, void* data)
44 : JSObject(prototype)
45{
46 init(exec, jsClass, data);
47}
48
49void JSCallbackObject::init(ExecState* exec, JSClassRef jsClass, void* data)
50{
51 m_privateData = data;
52 m_class = JSClassRetain(jsClass);
53
54 Vector<JSObjectInitializeCallback, 16> initRoutines;
55 do {
56 if (JSObjectInitializeCallback initialize = jsClass->initialize)
57 initRoutines.append(initialize);
58 } while ((jsClass = jsClass->parentClass));
59
60 // initialize from base to derived
61 for (int i = static_cast<int>(initRoutines.size()) - 1; i >= 0; i--) {
62 JSObjectInitializeCallback initialize = initRoutines[i];
63 initialize(toRef(exec), toRef(this));
64 }
65}
66
67JSCallbackObject::~JSCallbackObject()
68{
69 JSObjectRef thisRef = toRef(this);
70
71 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
72 if (JSObjectFinalizeCallback finalize = jsClass->finalize)
73 finalize(thisRef);
74
75 JSClassRelease(m_class);
76}
77
78UString JSCallbackObject::className() const
79{
80 if (!m_class->className.isNull())
81 return m_class->className;
82
83 return JSObject::className();
84}
85
86bool JSCallbackObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
87{
88 JSContextRef ctx = toRef(exec);
89 JSObjectRef thisRef = toRef(this);
90 JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
91
92 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
93 // optional optimization to bypass getProperty in cases when we only need to know if the property exists
94 if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
95 if (hasProperty(ctx, thisRef, propertyNameRef)) {
96 slot.setCustom(this, callbackGetter);
97 return true;
98 }
99 } else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
100 if (JSValueRef value = getProperty(ctx, thisRef, propertyNameRef, toRef(exec->exceptionSlot()))) {
101 // cache the value so we don't have to compute it again
102 // FIXME: This violates the PropertySlot design a little bit.
103 // We should either use this optimization everywhere, or nowhere.
104 slot.setCustom(reinterpret_cast<JSObject*>(toJS(value)), cachedValueGetter);
105 return true;
106 }
107 }
108
109 if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
110 if (staticValues->contains(propertyName.ustring().rep())) {
111 slot.setCustom(this, staticValueGetter);
112 return true;
113 }
114 }
115
116 if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
117 if (staticFunctions->contains(propertyName.ustring().rep())) {
118 slot.setCustom(this, staticFunctionGetter);
119 return true;
120 }
121 }
122 }
123
124 return JSObject::getOwnPropertySlot(exec, propertyName, slot);
125}
126
127bool JSCallbackObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
128{
129 return getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
130}
131
132void JSCallbackObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
133{
134 JSContextRef ctx = toRef(exec);
135 JSObjectRef thisRef = toRef(this);
136 JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
137 JSValueRef valueRef = toRef(value);
138
139 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
140 if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
141 if (setProperty(ctx, thisRef, propertyNameRef, valueRef, toRef(exec->exceptionSlot())))
142 return;
143 }
144
145 if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
146 if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
147 if (entry->attributes & kJSPropertyAttributeReadOnly)
148 return;
149 if (JSObjectSetPropertyCallback setProperty = entry->setProperty) {
150 if (setProperty(ctx, thisRef, propertyNameRef, valueRef, toRef(exec->exceptionSlot())))
151 return;
152 } else
153 throwError(exec, ReferenceError, "Writable static value property defined with NULL setProperty callback.");
154 }
155 }
156
157 if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
158 if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
159 if (entry->attributes & kJSPropertyAttributeReadOnly)
160 return;
161 putDirect(propertyName, value, attr); // put as override property
162 return;
163 }
164 }
165 }
166
167 return JSObject::put(exec, propertyName, value, attr);
168}
169
170void JSCallbackObject::put(ExecState* exec, unsigned propertyName, JSValue* value, int attr)
171{
172 return put(exec, Identifier::from(propertyName), value, attr);
173}
174
175bool JSCallbackObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
176{
177 JSContextRef ctx = toRef(exec);
178 JSObjectRef thisRef = toRef(this);
179 JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
180
181 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
182 if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
183 if (deleteProperty(ctx, thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
184 return true;
185 }
186
187 if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
188 if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
189 if (entry->attributes & kJSPropertyAttributeDontDelete)
190 return false;
191 return true;
192 }
193 }
194
195 if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
196 if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
197 if (entry->attributes & kJSPropertyAttributeDontDelete)
198 return false;
199 return true;
200 }
201 }
202 }
203
204 return JSObject::deleteProperty(exec, propertyName);
205}
206
207bool JSCallbackObject::deleteProperty(ExecState* exec, unsigned propertyName)
208{
209 return deleteProperty(exec, Identifier::from(propertyName));
210}
211
212bool JSCallbackObject::implementsConstruct() const
213{
214 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
215 if (jsClass->callAsConstructor)
216 return true;
217
218 return false;
219}
220
221JSObject* JSCallbackObject::construct(ExecState* exec, const List& args)
222{
223 JSContextRef execRef = toRef(exec);
224 JSObjectRef thisRef = toRef(this);
225
226 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
227 if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) {
228 int argumentCount = static_cast<int>(args.size());
229 Vector<JSValueRef, 16> arguments(argumentCount);
230 for (int i = 0; i < argumentCount; i++)
231 arguments[i] = toRef(args[i]);
232 return toJS(callAsConstructor(execRef, thisRef, argumentCount, arguments, toRef(exec->exceptionSlot())));
233 }
234 }
235
236 ASSERT(0); // implementsConstruct should prevent us from reaching here
237 return 0;
238}
239
240bool JSCallbackObject::implementsHasInstance() const
241{
242 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
243 if (jsClass->hasInstance)
244 return true;
245
246 return false;
247}
248
249bool JSCallbackObject::hasInstance(ExecState *exec, JSValue *value)
250{
251 JSContextRef execRef = toRef(exec);
252 JSObjectRef thisRef = toRef(this);
253
254 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
255 if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance)
256 return hasInstance(execRef, thisRef, toRef(value), toRef(exec->exceptionSlot()));
257
258 ASSERT(0); // implementsHasInstance should prevent us from reaching here
259 return 0;
260}
261
262
263bool JSCallbackObject::implementsCall() const
264{
265 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
266 if (jsClass->callAsFunction)
267 return true;
268
269 return false;
270}
271
272JSValue* JSCallbackObject::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
273{
274 JSContextRef execRef = toRef(exec);
275 JSObjectRef thisRef = toRef(this);
276 JSObjectRef thisObjRef = toRef(thisObj);
277
278 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
279 if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) {
280 int argumentCount = static_cast<int>(args.size());
281 Vector<JSValueRef, 16> arguments(argumentCount);
282 for (int i = 0; i < argumentCount; i++)
283 arguments[i] = toRef(args[i]);
284 return toJS(callAsFunction(execRef, thisRef, thisObjRef, argumentCount, arguments, toRef(exec->exceptionSlot())));
285 }
286 }
287
288 ASSERT(0); // implementsCall should prevent us from reaching here
289 return 0;
290}
291
292void JSCallbackObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
293{
294 JSContextRef execRef = toRef(exec);
295 JSObjectRef thisRef = toRef(this);
296
297 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
298 if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames)
299 getPropertyNames(execRef, thisRef, toRef(&propertyNames));
300
301 if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
302 typedef OpaqueJSClass::StaticValuesTable::const_iterator iterator;
303 iterator end = staticValues->end();
304 for (iterator it = staticValues->begin(); it != end; ++it) {
305 UString::Rep* name = it->first.get();
306 StaticValueEntry* entry = it->second;
307 if (entry->getProperty && !(entry->attributes & kJSPropertyAttributeDontEnum))
308 propertyNames.add(Identifier(name));
309 }
310 }
311
312 if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
313 typedef OpaqueJSClass::StaticFunctionsTable::const_iterator iterator;
314 iterator end = staticFunctions->end();
315 for (iterator it = staticFunctions->begin(); it != end; ++it) {
316 UString::Rep* name = it->first.get();
317 StaticFunctionEntry* entry = it->second;
318 if (!(entry->attributes & kJSPropertyAttributeDontEnum))
319 propertyNames.add(Identifier(name));
320 }
321 }
322 }
323
324 JSObject::getPropertyNames(exec, propertyNames);
325}
326
327double JSCallbackObject::toNumber(ExecState* exec) const
328{
329 JSContextRef ctx = toRef(exec);
330 JSObjectRef thisRef = toRef(this);
331
332 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
333 if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType)
334 if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeNumber, toRef(exec->exceptionSlot())))
335 return toJS(value)->getNumber();
336
337 return JSObject::toNumber(exec);
338}
339
340UString JSCallbackObject::toString(ExecState* exec) const
341{
342 JSContextRef ctx = toRef(exec);
343 JSObjectRef thisRef = toRef(this);
344
345 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
346 if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType)
347 if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeString, toRef(exec->exceptionSlot())))
348 return toJS(value)->getString();
349
350 return JSObject::toString(exec);
351}
352
353void JSCallbackObject::setPrivate(void* data)
354{
355 m_privateData = data;
356}
357
358void* JSCallbackObject::getPrivate()
359{
360 return m_privateData;
361}
362
363bool JSCallbackObject::inherits(JSClassRef c) const
364{
365 for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
366 if (jsClass == c)
367 return true;
368
369 return false;
370}
371
372JSValue* JSCallbackObject::cachedValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
373{
374 JSValue* v = slot.slotBase();
375 ASSERT(v);
376 return v;
377}
378
379JSValue* JSCallbackObject::staticValueGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
380{
381 ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
382 JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
383
384 JSObjectRef thisRef = toRef(thisObj);
385 JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
386
387 for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
388 if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues)
389 if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep()))
390 if (JSObjectGetPropertyCallback getProperty = entry->getProperty)
391 if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
392 return toJS(value);
393
394 return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback.");
395}
396
397JSValue* JSCallbackObject::staticFunctionGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
398{
399 ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
400 JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
401
402 if (JSValue* cachedOrOverrideValue = thisObj->getDirect(propertyName))
403 return cachedOrOverrideValue;
404
405 for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass) {
406 if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
407 if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
408 if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) {
409 JSObject* o = new JSCallbackFunction(exec, callAsFunction, propertyName);
410 thisObj->putDirect(propertyName, o, entry->attributes);
411 return o;
412 }
413 }
414 }
415 }
416
417 return throwError(exec, ReferenceError, "Static function property defined with NULL callAsFunction callback.");
418}
419
420JSValue* JSCallbackObject::callbackGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
421{
422 ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
423 JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
424
425 JSObjectRef thisRef = toRef(thisObj);
426 JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
427
428 for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
429 if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty)
430 if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
431 return toJS(value);
432
433 return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist.");
434}
435
436} // namespace KJS
Note: See TracBrowser for help on using the repository browser.