JSValue::isConstructor and JSValue::isFunction should check getConstructData and...
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 Feb 2016 22:24:51 +0000 (22:24 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 Feb 2016 22:24:51 +0000 (22:24 +0000)
https://bugs.webkit.org/show_bug.cgi?id=154552

Reviewed by Mark Lam.

ES6 Proxy breaks our isFunction() and isConstructor() JSValue methods.
They return false on a Proxy with internal [[Call]] and [[Construct]]
properties. It seems safest, most forward looking, and most adherent
to the specification to check getCallData() and getConstructData() to
implement these functions.

* runtime/InternalFunction.cpp:
(JSC::InternalFunction::createSubclassStructure):
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::isFunction):
(JSC::JSValue::isConstructor):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/InternalFunction.cpp
Source/JavaScriptCore/runtime/JSCJSValueInlines.h

index 59c9788..337652d 100644 (file)
@@ -1,3 +1,22 @@
+2016-02-22  Saam barati  <sbarati@apple.com>
+
+        JSValue::isConstructor and JSValue::isFunction should check getConstructData and getCallData
+        https://bugs.webkit.org/show_bug.cgi?id=154552
+
+        Reviewed by Mark Lam.
+
+        ES6 Proxy breaks our isFunction() and isConstructor() JSValue methods.
+        They return false on a Proxy with internal [[Call]] and [[Construct]]
+        properties. It seems safest, most forward looking, and most adherent
+        to the specification to check getCallData() and getConstructData() to
+        implement these functions.
+
+        * runtime/InternalFunction.cpp:
+        (JSC::InternalFunction::createSubclassStructure):
+        * runtime/JSCJSValueInlines.h:
+        (JSC::JSValue::isFunction):
+        (JSC::JSValue::isConstructor):
+
 2016-02-22  Keith Miller  <keith_miller@apple.com>
 
         Bound functions should use the prototype of the function being bound
index bb23d45..1b029cf 100644 (file)
@@ -84,7 +84,7 @@ Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue ne
     VM& vm = exec->vm();
     // We allow newTarget == JSValue() because the API needs to be able to create classes without having a real JS frame.
     // Since we don't allow subclassing in the API we just treat newTarget == JSValue() as newTarget == exec->callee()
-    ASSERT(!newTarget || newTarget.isFunction());
+    ASSERT(!newTarget || newTarget.isConstructor());
 
     if (newTarget && newTarget != exec->callee()) {
         // newTarget may be an InternalFunction if we were called from Reflect.construct.
index 6ce9615..3b2fdcf 100644 (file)
@@ -679,17 +679,20 @@ inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject
 
 inline bool JSValue::isFunction() const
 {
-    return isCell() && (asCell()->inherits(JSFunction::info()) || asCell()->inherits(InternalFunction::info()));
+    if (!isCell())
+        return false;
+    JSCell* cell = asCell();
+    CallData ignored;
+    return cell->methodTable()->getCallData(cell, ignored) != CallTypeNone;
 }
 
-// FIXME: We could do this in a smarter way. See: https://bugs.webkit.org/show_bug.cgi?id=153670
 inline bool JSValue::isConstructor() const
 {
-    if (isFunction()) {
-        ConstructData data;
-        return getConstructData(*this, data) != ConstructTypeNone;
-    }
-    return false;
+    if (!isCell())
+        return false;
+    JSCell* cell = asCell();
+    ConstructData ignored;
+    return cell->methodTable()->getConstructData(cell, ignored) != ConstructTypeNone;
 }
 
 // this method is here to be after the inline declaration of JSCell::inherits