4eviewed by Geoff.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Jul 2006 09:55:55 +0000 (09:55 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Jul 2006 09:55:55 +0000 (09:55 +0000)
        - add handling of hasInstance callback for API objects

        * API/JSCallbackObject.cpp:
        (KJS::JSCallbackObject::implementsHasInstance): Check if callback is present.
        (KJS::JSCallbackObject::hasInstance): Invoke appropriate callback.
        * API/JSCallbackObject.h:
        * API/JSClassRef.cpp:
        * API/JSObjectRef.h:
        * API/testapi.c:
        (MyObject_hasInstance): Test case; should match what construct would do.
        * API/testapi.js:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15384 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/API/JSCallbackObject.cpp
JavaScriptCore/API/JSCallbackObject.h
JavaScriptCore/API/JSClassRef.cpp
JavaScriptCore/API/JSObjectRef.h
JavaScriptCore/API/testapi.c
JavaScriptCore/API/testapi.js
JavaScriptCore/ChangeLog

index d05efc833b900a712668589f9098ca68a8c0787a..06f2fd6c3b6cc34879bec5e95693e73eb5d32536 100644 (file)
@@ -235,6 +235,29 @@ JSObject* JSCallbackObject::construct(ExecState* exec, const List& args)
     return 0;
 }
 
+bool JSCallbackObject::implementsHasInstance() const
+{
+    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
+        if (jsClass->callbacks.hasInstance)
+            return true;
+
+    return false;
+}
+
+bool JSCallbackObject::hasInstance(ExecState *exec, JSValue *value)
+{
+    JSContextRef execRef = toRef(exec);
+    JSObjectRef thisRef = toRef(this);
+
+    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
+        if (JSObjectHasInstanceCallback hasInstance = jsClass->callbacks.hasInstance)
+            return hasInstance(execRef, thisRef, toRef(value), toRef(exec->exceptionSlot()));
+
+    ASSERT(0); // implementsHasInstance should prevent us from reaching here
+    return 0;
+}
+
+
 bool JSCallbackObject::implementsCall() const
 {
     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
index 77a5b1b3a7160a4bd3dbf8685fdabe4d9ac98ab4..226427b2d11eb61556a62a3bf14d71f5dfd5a121 100644 (file)
@@ -54,6 +54,9 @@ public:
     virtual bool implementsConstruct() const;
     virtual JSObject* construct(ExecState*, const List& args);
 
+    virtual bool implementsHasInstance() const;
+    virtual bool hasInstance(ExecState *exec, JSValue *value);
+
     virtual bool implementsCall() const;
     virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List &args);
 
index bfa3e8517c2510ed629a86c6648c2f70d44a51a0..3bf730dcab61b93cd0979c86b1083e712558def9 100644 (file)
@@ -30,7 +30,7 @@
 
 using namespace KJS;
 
-const JSObjectCallbacks kJSObjectCallbacksNone = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+const JSObjectCallbacks kJSObjectCallbacksNone = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
 JSClassRef JSClassCreate(JSStaticValue* staticValues, JSStaticFunction* staticFunctions, const JSObjectCallbacks* callbacks, JSClassRef parentClass)
 {
index f8532ba2e53184eb618b4bad203a7d7a9b244f78..c2c384830702df997a60452f4b0183da1b0d3ab3 100644 (file)
@@ -193,7 +193,7 @@ typedef JSValueRef
 
 /*! 
 @typedef JSObjectCallAsConstructorCallback
-@abstract The callback invoked when an object is used as a constructor in a 'new' statement.
+@abstract The callback invoked when an object is used as a constructor in a 'new' expression.
 @param context The current execution context.
 @param constructor A JSObject that is the constructor being called.
 @param argc An integer count of the number of arguments in argv.
@@ -206,11 +206,33 @@ JSObjectRef CallAsConstructor(JSContextRef context, JSObjectRef constructor, siz
 
 If your callback were invoked by the JavaScript expression 'new myConstructorFunction()', constructor would be set to myConstructorFunction.
 
-If this callback is NULL, using your object as a constructor in a 'new' statement will throw an exception.
+If this callback is NULL, using your object as a constructor in a 'new' expression will throw an exception.
 */
 typedef JSObjectRef 
 (*JSObjectCallAsConstructorCallback) (JSContextRef context, JSObjectRef constructor, size_t argc, JSValueRef argv[], JSValueRef* exception);
 
+/*! 
+@typedef JSObjectHasInstanceCallback
+@abstract The callback invoked when an object is used in an 'instanceof' expression.
+@param context The current execution context.
+@param constructor The JSObject receiving the hasInstance request
+@param possibleInstance The JSValue being tested to determine if it is an instance of constructor.
+@param exception A pointer to a JSValueRef in which to return an exception, if any.
+@result true if possibleInstance is an instance of constructor, otherwise false
+
+@discussion If you named your function HasInstance, you would declare it like this:
+
+bool HasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception);
+
+If your callback were invoked by the JavaScript expression 'someValue instanceof myObject', constructor would be set to myObject and possibleInstance would be set to someValue..
+
+If this callback is NULL, using your object in an 'instanceof' will always return false.
+
+Standard JavaScript practice calls for objects that implement the callAsConstructor callback to implement the hasInstance callback as well.
+*/
+typedef bool 
+(*JSObjectHasInstanceCallback)  (JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception);
+
 /*! 
 @typedef JSObjectConvertToTypeCallback
 @abstract The callback invoked when converting an object to a particular JavaScript type.
@@ -240,7 +262,8 @@ typedef JSValueRef
 @field deleteProperty The callback invoked when deleting a given property.
 @field getPropertyList The callback invoked when adding an object's properties to a property list.
 @field callAsFunction The callback invoked when an object is called as a function.
-@field callAsConstructor The callback invoked when an object is used as a constructor in a 'new' statement.
+@field hasInstance The callback invoked when an object is used in an 'instanceof' expression.
+@field callAsConstructor The callback invoked when an object is used as a constructor in a 'new' expression.
 @field convertToType The callback invoked when converting an object to a particular JavaScript type.
 */
 typedef struct {
@@ -254,6 +277,7 @@ typedef struct {
     JSObjectAddPropertiesToListCallback addPropertiesToList;
     JSObjectCallAsFunctionCallback      callAsFunction;
     JSObjectCallAsConstructorCallback   callAsConstructor;
+    JSObjectHasInstanceCallback         hasInstance;
     JSObjectConvertToTypeCallback       convertToType;
 } JSObjectCallbacks;
 
@@ -343,7 +367,7 @@ JSObjectRef JSObjectMakeFunction(JSContextRef context, JSObjectCallAsFunctionCal
 @function
 @abstract Convenience method for creating a JavaScript constructor with a given callback as its implementation.
 @param context The execution context to use.
-@param callAsConstructor The JSObjectCallAsConstructorCallback to invoke when the constructor is used in a 'new' statement.
+@param callAsConstructor The JSObjectCallAsConstructorCallback to invoke when the constructor is used in a 'new' expression.
 @result A JSObject that is a constructor. The object's prototype will be the default object prototype.
 */
 JSObjectRef JSObjectMakeConstructor(JSContextRef context, JSObjectCallAsConstructorCallback callAsConstructor);
index 27f42bcc8ce58384e5f96dd7a913bab894ea0722..8714ee0e4429d4f45fbf5d0774cc91dc47111f0a 100644 (file)
@@ -200,6 +200,17 @@ static JSObjectRef MyObject_callAsConstructor(JSContextRef context, JSObjectRef
     return JSValueToObject(context, JSValueMakeNumber(0));
 }
 
+static bool MyObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
+{
+    UNUSED_PARAM(context);
+
+    JSStringRef numberString = JSStringCreateWithUTF8CString("Number");
+    JSObjectRef numberConstructor = JSValueToObject(context, JSObjectGetProperty(context, JSContextGetGlobalObject(context), numberString));
+    JSStringRelease(numberString);
+
+    return JSValueIsInstanceOfConstructor(context, possibleValue, numberConstructor);
+}
+
 static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
 {
     UNUSED_PARAM(context);
@@ -228,16 +239,17 @@ static void MyObject_finalize(JSObjectRef object)
 
 JSObjectCallbacks MyObject_callbacks = {
     0,
-    &MyObject_initialize,
-    &MyObject_finalize,
-    &MyObject_hasProperty,
-    &MyObject_getProperty,
-    &MyObject_setProperty,
-    &MyObject_deleteProperty,
-    &MyObject_getPropertyList,
-    &MyObject_callAsFunction,
-    &MyObject_callAsConstructor,
-    &MyObject_convertToType,
+    MyObject_initialize,
+    MyObject_finalize,
+    MyObject_hasProperty,
+    MyObject_getProperty,
+    MyObject_setProperty,
+    MyObject_deleteProperty,
+    MyObject_getPropertyList,
+    MyObject_callAsFunction,
+    MyObject_callAsConstructor,
+    MyObject_hasInstance,
+    MyObject_convertToType,
 };
 
 static JSClassRef MyObject_class(JSContextRef context)
index 1be438dd167d68e65c16757fb22484663bcfa3b3..e2cddb4df7e5bc1ee3a0af904752a96beccf481e 100644 (file)
@@ -81,3 +81,5 @@ shouldBe("typeof MyConstructor", "object");
 constructedObject = new MyConstructor(1);
 shouldBe("typeof constructedObject", "object");
 shouldBe("constructedObject.value", 1);
+shouldBe("(new MyObject()) instanceof MyObject", true);
+shouldBe("(new Object()) instanceof MyObject", false);
index b7db2feee123c48cc36bd5c081f483af8144309c..2ec36cb9ff41be99386743be9c58000964e09515 100644 (file)
@@ -1,3 +1,19 @@
+2006-07-12  Maciej Stachowiak  <mjs@apple.com>
+
+        4eviewed by Geoff.
+        
+        - add handling of hasInstance callback for API objects
+
+        * API/JSCallbackObject.cpp:
+        (KJS::JSCallbackObject::implementsHasInstance): Check if callback is present.
+        (KJS::JSCallbackObject::hasInstance): Invoke appropriate callback.
+        * API/JSCallbackObject.h:
+        * API/JSClassRef.cpp:
+        * API/JSObjectRef.h:
+        * API/testapi.c:
+        (MyObject_hasInstance): Test case; should match what construct would do.
+        * API/testapi.js:
+
 2006-07-11  Geoffrey Garen  <ggaren@apple.com>
 
         Reviewed by Maciej.