22 #ifndef _KJS_BINDING_H_
23 #define _KJS_BINDING_H_
25 #include <khtml_export.h>
26 #include <kjs/interpreter.h>
27 #include <kjs/global.h>
28 #include <wtf/HashMap.h>
30 #include <dom/dom_node.h>
34 #include <kjs/lookup.h>
35 #include <kjs/function.h>
36 #include <kjs/JSVariableObject.h>
37 #include <kjs/object_object.h>
38 #include <misc/shared.h>
42 #define KJS_CHECK_THIS( ClassName, theObj ) \
43 if (!theObj || !theObj->inherits(&ClassName::info)) { \
44 KJS::UString errMsg = "Attempt at calling a function that expects a "; \
45 errMsg += ClassName::info.className; \
47 errMsg += theObj->className(); \
48 KJS::JSObject *err = KJS::Error::create(exec, KJS::TypeError, errMsg.ascii()); \
49 exec->setException(err); \
56 class LiveConnectExtension;
73 QString exceptionToString(ExecState *exec, JSValue *exception);
82 DOMObject(JSObject *proto) : JSObject(proto) {}
84 bool shouldMark()
const
86 return !_prop.isEmpty();
109 DOMObject *getDOMObject(
void *objectHandle)
111 DOMObject *existing = allDomObjects()->get(objectHandle);
113 m_domObjects.set(objectHandle, existing);
118 void putDOMObject(
void *objectHandle,
DOMObject *obj)
120 allDomObjects()->set(objectHandle, obj);
121 m_domObjects.set(objectHandle, obj);
124 static void forgetDOMObject(
void *objectHandle);
128 m_domObjects.clear();
134 void mark(
bool isMain)
override;
149 void setInlineCode(
bool inlineCode)
151 m_inlineCode = inlineCode;
153 void setProcessingTimerCallback(
bool timerCallback)
155 m_timerCallback = timerCallback;
167 void startCPUGuard();
170 static void turnOffCPUGuard()
172 s_disableCPUGuard =
true;
175 khtml::ChildFrame *m_frame;
176 HashMap<void *, DOMObject *> m_domObjects;
177 static HashMap<void *, DOMObject *> *s_allDomObjects;
178 static HashMap<void *, DOMObject *> *allDomObjects()
180 if (!s_allDomObjects) {
181 s_allDomObjects =
new HashMap<void *, DOMObject *>();
183 return s_allDomObjects;
188 bool m_timerCallback;
189 static bool s_disableCPUGuard;
200 template<
typename Wrapper>
201 JSValue *getWrapper(ExecState *exec,
typename Wrapper::wrappedType *g)
203 DOMObject *ret =
nullptr;
208 ScriptInterpreter *interp =
static_cast<ScriptInterpreter *
>(exec->dynamicInterpreter());
209 if ((ret = interp->getDOMObject(g))) {
213 ret =
new Wrapper(exec, g);
214 interp->putDOMObject(g, ret);
218 template<
typename Wrapped>
219 class DOMWrapperObject :
public DOMObject
222 typedef Wrapped wrappedType;
223 typedef DOMWrapperObject<Wrapped> WrapperBase;
225 DOMWrapperObject(JSObject *proto, Wrapped *wrapee):
226 DOMObject(proto), m_impl(wrapee)
229 virtual ~DOMWrapperObject()
231 ScriptInterpreter::forgetDOMObject(m_impl.get());
234 bool toBoolean(ExecState *)
const override
243 const Wrapped *impl()
const
248 SharedPtr<Wrapped> m_impl;
254 template<
class FuncImp,
class ThisImp>
255 inline void getSlotFromEntry(
const HashEntry *entry, ThisImp *thisObj, PropertySlot &slot)
257 if (entry->attr & Function) {
258 slot.setStaticEntry(thisObj, entry, staticFunctionGetter<FuncImp>);
260 slot.setStaticEntry(thisObj, entry, staticValueGetter<ThisImp>);
268 template <
class FuncImp,
class ThisImp>
269 inline bool getStaticOwnPropertySlot(
const HashTable *table,
270 ThisImp *thisObj,
const Identifier &propertyName, PropertySlot &slot)
278 if (entry->attr & Function) {
279 slot.setStaticEntry(thisObj, entry, staticFunctionGetter<FuncImp>);
281 slot.setStaticEntry(thisObj, entry, staticValueGetter<ThisImp>);
290 template<
class ThisImp>
291 inline bool getStaticOwnValueSlot(
const HashTable *table,
292 ThisImp *thisObj,
const Identifier &propertyName, PropertySlot &slot)
299 assert(!(entry->attr & Function));
300 slot.setStaticEntry(thisObj, entry, staticValueGetter<ThisImp>);
305 template<
class JSTypeImp>
306 JSValue *indexGetterAdapter(ExecState *exec, JSObject *,
unsigned,
const PropertySlot &slot)
308 JSTypeImp *thisObj =
static_cast<JSTypeImp *
>(slot.slotBase());
309 return thisObj->indexGetter(exec, slot.index());
316 template<
class ThisImp,
class BaseObj>
317 inline bool getIndexSlot(ThisImp *thisObj,
const BaseObj &listObj,
318 const Identifier &propertyName, PropertySlot &slot)
321 unsigned u = propertyName.toArrayIndex(&ok);
322 if (ok && u < listObj.length()) {
323 slot.setCustomIndex(thisObj, u, indexGetterAdapter<ThisImp>);
332 template<
class ThisImp>
333 inline bool getIndexSlot(ThisImp *thisObj,
unsigned lengthLimit,
334 const Identifier &propertyName, PropertySlot &slot)
337 unsigned u = propertyName.toArrayIndex(&ok);
338 if (ok && u < lengthLimit) {
339 slot.setCustomIndex(thisObj, u, indexGetterAdapter<ThisImp>);
345 template<
class ThisImp>
346 inline bool getIndexSlot(ThisImp *thisObj,
int lengthLimit,
347 const Identifier &propertyName, PropertySlot &slot)
349 return getIndexSlot(thisObj, (
unsigned)lengthLimit, propertyName, slot);
355 template<
class ThisImp>
356 inline bool getIndexSlot(ThisImp *thisObj,
const Identifier &propertyName, PropertySlot &slot)
359 unsigned u = propertyName.toArrayIndex(&ok);
361 slot.setCustomIndex(thisObj, u, indexGetterAdapter<ThisImp>);
368 JSValue *valueGetterAdapter(ExecState *exec, JSObject *,
const Identifier &,
const PropertySlot &slot);
374 inline bool getImmediateValueSlot(JSObject *thisObj, JSValue *value, PropertySlot &slot)
376 slot.setCustomValue(thisObj, value, valueGetterAdapter);
383 template<
class DOMObj,
class KJSDOMObj>
384 inline JSValue *cacheDOMObject(ExecState *exec, DOMObj *domObj)
390 ScriptInterpreter *interp =
static_cast<ScriptInterpreter *
>(exec->dynamicInterpreter());
391 if ((ret = interp->getDOMObject(domObj))) {
394 ret =
new KJSDOMObj(exec, domObj);
395 interp->putDOMObject(domObj, ret);
403 DOM::NodeImpl *toNode(JSValue *);
412 DOM::DOMString valueToStringWithNullCheck(ExecState *exec, JSValue *v);
417 QVariant ValueToVariant(ExecState *exec, JSValue *val);
420 void setDOMException(ExecState *exec,
int DOMExceptionCode);
423 class DOMExceptionTranslator
426 explicit DOMExceptionTranslator(ExecState *exec) : m_exec(exec), m_code(0) { }
427 ~DOMExceptionTranslator()
429 setDOMException(m_exec, m_code);
450 inline JSCell *jsString(
const QString &s)
452 return jsString(UString(s));
458 #define DEFINE_PSEUDO_CONSTRUCTOR(ClassName) \
459 class ClassName : public DOMObject { \
461 ClassName(ExecState *); \
462 virtual const ClassInfo* classInfo() const { return &info; } \
463 static const ClassInfo info; \
464 static JSObject* self(ExecState *exec); \
465 virtual bool implementsHasInstance() const; \
468 #define IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,ParentProto) \
469 const ClassInfo Class::info = { ClassName, nullptr, nullptr, nullptr }; \
470 Class::Class(ExecState* exec): DOMObject(ParentProto) {\
472 exec->lexicalInterpreter()->globalObject()->put(exec, "[[" ClassName ".constructor]]", this, KJS::Internal | KJS::DontEnum); \
473 JSObject* proto = ProtoClass::self(exec); \
474 putDirect(exec->propertyNames().prototype, proto, DontDelete|ReadOnly); \
476 JSObject* Class::self(ExecState *exec) { \
477 return cacheGlobalObject<Class>(exec, "[[" ClassName ".constructor]]"); \
479 bool Class::implementsHasInstance() const { \
483 #define IMPLEMENT_PSEUDO_CONSTRUCTOR(Class,ClassName,ProtoClass) \
484 IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,exec->lexicalInterpreter()->builtinObjectPrototype())
486 #define IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(Class,ClassName,ProtoClass,ParentProtoClass) \
487 IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,ParentProtoClass::self(exec))
491 #define DEFINE_CONSTANT_TABLE(Class) \
492 class Class : public DOMObject { \
494 Class(ExecState *exec): DOMObject(exec->lexicalInterpreter()->builtinObjectPrototype()) {} \
496 using KJS::JSObject::getOwnPropertySlot;\
497 virtual bool getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot);\
498 JSValue* getValueProperty(ExecState *exec, int token) const; \
499 virtual const ClassInfo* classInfo() const { return &info; } \
500 static const ClassInfo info; \
501 static JSObject* self(ExecState *exec);\
502 static Identifier* s_name; \
503 static Identifier* name(); \
507 #define IMPLEMENT_CONSTANT_TABLE(Class,ClassName) \
508 bool Class::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) \
510 return getStaticValueSlot<Class, DOMObject>(exec, &Class##Table, this, propertyName, slot);\
512 JSValue* Class::getValueProperty(ExecState * , int token) const { \
514 return jsNumber((unsigned int)token); \
516 JSObject* Class::self(ExecState *exec) { \
517 return cacheGlobalObject<Class>(exec, *name()); \
519 Identifier* Class::s_name = nullptr; \
520 Identifier* Class::name() { \
521 if (!s_name) s_name = new Identifier("[[" ClassName ".constant_table]]"); \
524 const ClassInfo Class::info = { ClassName, nullptr, &Class##Table, nullptr };
527 #define KJS_EMPTY_PROTOTYPE_IMP(ClassName, ClassProto, ProtoCode) \
528 class ClassProto : public JSObject { \
529 friend JSObject* KJS_CACHEGLOBALOBJECT_NS cacheGlobalObject<ClassProto>(ExecState *exec, const Identifier &propertyName); \
531 static JSObject* self(ExecState *exec) { \
532 return KJS_CACHEGLOBALOBJECT_NS cacheGlobalObject<ClassProto>(exec, *name()); \
534 virtual const ClassInfo *classInfo() const { return &info; } \
535 static const ClassInfo info; \
537 ClassProto( ExecState *exec ) \
538 : JSObject( ProtoCode ) {} \
540 static Identifier* s_name; \
541 static Identifier* name() { \
542 if (!s_name) s_name = new Identifier("[[" ClassName ".prototype]]"); \
546 Identifier* ClassProto::s_name = nullptr; \
547 const ClassInfo ClassProto::info = { ClassName, nullptr, nullptr, nullptr };
549 #define KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE(ClassName, ClassProto, ClassProtoProto) \
550 KJS_EMPTY_PROTOTYPE_IMP(ClassName, ClassProto, ClassProtoProto::self(exec))