Changeset 15443 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Jul 14, 2006, 9:10:31 PM (19 years ago)
Author:
ggaren
Message:

Reviewed by Maciej.


  • Finalized exception handling in the API.


setProperty can throw because it throws for built-in arrays. getProperty
and deleteProperty can throw because setProperty can throw and we want
to be consistent, and also because they seem like "actions." callAsFunction,
callAsConstructor, and hasInstance can throw, because they caan throw for
all built-ins.


toBoolean can't throw because it's defined that way in the spec.


  • Documented that toBoolean and toObject can't be overridden by custom objects because they're defined that way in the spec.
Location:
trunk/JavaScriptCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/API/JSCallbackObject.cpp

    r15400 r15443  
    9090        // optional optimization to bypass getProperty in cases when we only need to know if the property exists
    9191        if (JSObjectHasPropertyCallback hasProperty = jsClass->callbacks.hasProperty) {
    92             if (hasProperty(context, thisRef, propertyNameRef, toRef(exec->exceptionSlot()))) {
     92            if (hasProperty(context, thisRef, propertyNameRef)) {
    9393                slot.setCustom(this, callbackGetter);
    9494                return true;
     
    322322}
    323323
    324 bool JSCallbackObject::toBoolean(ExecState* exec) const
    325 {
    326     JSContextRef context = toRef(exec);
    327     JSObjectRef thisRef = toRef(this);
    328 
    329     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
    330         if (JSObjectConvertToTypeCallback convertToType = jsClass->callbacks.convertToType)
    331             if (JSValueRef value = convertToType(context, thisRef, kJSTypeBoolean, toRef(exec->exceptionSlot())))
    332                 return toJS(value)->getBoolean();
    333 
    334     return JSObject::toBoolean(exec);
    335 }
    336 
    337324double JSCallbackObject::toNumber(ExecState* exec) const
    338325{
  • trunk/JavaScriptCore/API/JSCallbackObject.h

    r15385 r15443  
    6363    virtual void getPropertyList(ReferenceList& propertyList, bool recursive);
    6464
    65     virtual bool toBoolean(ExecState*) const;
    6665    virtual double toNumber(ExecState*) const;
    6766    virtual UString toString(ExecState*) const;
  • trunk/JavaScriptCore/API/JSObjectRef.cpp

    r15434 r15443  
    121121}
    122122
    123 JSValueRef JSObjectGetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName)
     123JSValueRef JSObjectGetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
    124124{
    125125    JSLock lock;
     
    130130    JSValue* jsValue = jsObject->get(exec, Identifier(nameRep));
    131131    if (jsValue->isUndefined())
    132         return 0;
     132        jsValue = 0;
     133    if (exec->hadException()) {
     134        if (exception)
     135            *exception = toRef(exec->exception());
     136        exec->clearException();
     137    }
    133138    return toRef(jsValue);
    134139}
    135140
    136 void JSObjectSetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes)
     141void JSObjectSetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
    137142{
    138143    JSLock lock;
     
    143148   
    144149    jsObject->put(exec, Identifier(nameRep), jsValue, attributes);
     150    if (exec->hadException()) {
     151        if (exception)
     152            *exception = toRef(exec->exception());
     153        exec->clearException();
     154    }
    145155}
    146156
     
    168178}
    169179
    170 bool JSObjectDeleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName)
     180bool JSObjectDeleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
    171181{
    172182    JSLock lock;
     
    175185    UString::Rep* nameRep = toJS(propertyName);
    176186
    177     return jsObject->deleteProperty(exec, Identifier(nameRep));
     187    bool result = jsObject->deleteProperty(exec, Identifier(nameRep));
     188    if (exec->hadException()) {
     189        if (exception)
     190            *exception = toRef(exec->exception());
     191        exec->clearException();
     192    }
     193    return result;
    178194}
    179195
  • trunk/JavaScriptCore/API/JSObjectRef.h

    r15434 r15443  
    8888@param object The JSObject to search for the property.
    8989@param propertyName A JSString containing the name of the property look up.
    90 @param exception A pointer to a JSValueRef in which to return an exception, if any.
    9190@result true if object has the property, otherwise false.
    9291@discussion If you named your function HasProperty, you would declare it like this:
    9392
    94 bool HasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
     93bool HasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName);
    9594
    9695If this function returns false, the hasProperty request forwards to object's static property table, then its parent class chain (which includes the default object class), then its prototype chain.
    9796
    98 This callback enables optimization in cases where only a property's existence needs to be known, not its value, and computing its value would be expensive. If this callback is NULL, the getProperty callback will be used to service hasProperty requests.
     97This callback enables optimization in cases where only a property's existence needs to be known, not its value, and computing its value would be expensive.
     98
     99If this callback is NULL, the getProperty callback will be used to service hasProperty requests.
    99100*/
    100101typedef bool
    101 (*JSObjectHasPropertyCallback) (JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
     102(*JSObjectHasPropertyCallback) (JSContextRef context, JSObjectRef object, JSStringRef propertyName);
    102103
    103104/*!
     
    212213/*!
    213214@typedef JSObjectHasInstanceCallback
    214 @abstract The callback invoked when an object is used in an 'instanceof' expression.
    215 @param context The current execution context.
    216 @param constructor The JSObject receiving the hasInstance request
     215@abstract hasInstance The callback invoked when an object is used as the target of an 'instanceof' expression.
     216@param context The current execution context.
     217@param constructor The JSObject that is the target of the 'instanceof' expression.
    217218@param possibleInstance The JSValue being tested to determine if it is an instance of constructor.
    218219@param exception A pointer to a JSValueRef in which to return an exception, if any.
    219 @result true if possibleInstance is an instance of constructor, otherwise false
     220@result true if possibleInstance is an instance of constructor, otherwise false.
    220221
    221222@discussion If you named your function HasInstance, you would declare it like this:
     
    223224bool HasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception);
    224225
    225 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..
    226 
    227 If this callback is NULL, using your object in an 'instanceof' will always return false.
     226If your callback were invoked by the JavaScript expression 'someValue instanceof myObject', constructor would be set to myObject and possibleInstance would be set to someValue.
     227
     228If this callback is NULL, 'instanceof' expressions that target your object will return false.
    228229
    229230Standard JavaScript practice calls for objects that implement the callAsConstructor callback to implement the hasInstance callback as well.
     
    245246
    246247If this function returns false, the conversion request forwards to object's parent class chain (which includes the default object class).
     248
     249This function is only invoked when converting an object to number or string. An object converted to boolean is 'true.' An object converted to object is itself.
    247250*/
    248251typedef JSValueRef
     
    261264@field addPropertiesToList The callback invoked when adding an object's properties to a property list.
    262265@field callAsFunction The callback invoked when an object is called as a function.
    263 @field hasInstance The callback invoked when an object is used in an 'instanceof' expression.
     266@field hasInstance The callback invoked when an object is used as the target of an 'instanceof' expression.
    264267@field callAsConstructor The callback invoked when an object is used as a constructor in a 'new' expression.
    265268@field convertToType The callback invoked when converting an object to a particular JavaScript type.
     
    414417@param object The JSObject whose property you want to get.
    415418@param propertyName A JSString containing the property's name.
     419@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
    416420@result The property's value if object has the property, otherwise NULL.
    417421*/
    418 JSValueRef JSObjectGetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName);
     422JSValueRef JSObjectGetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
    419423
    420424/*!
     
    425429@param propertyName A JSString containing the property's name.
    426430@param value A JSValue to use as the property's value.
     431@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
    427432@param attributes A logically ORed set of JSPropertyAttributes to give to the property.
    428433*/
    429 void JSObjectSetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes);
     434void JSObjectSetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception);
    430435
    431436/*!
     
    435440@param object The JSObject whose property you want to delete.
    436441@param propertyName A JSString containing the property's name.
     442@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
    437443@result true if the delete operation succeeds, otherwise false (for example, if the property has the kJSPropertyAttributeDontDelete attribute set).
    438444*/
    439 bool JSObjectDeleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName);
     445bool JSObjectDeleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
    440446
    441447/*!
     
    496502@param argc An integer count of the number of arguments in argv.
    497503@param argv A JSValue array of the  arguments to pass to the function.
    498 @param exception A pointer to a JSValueRef in which to store an uncaught exception, if any. Pass NULL if you do not care to store an uncaught exception.
    499 @result The JSValue that results from calling object as a function, or NULL if an uncaught exception is thrown or object is not a function.
     504@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
     505@result The JSValue that results from calling object as a function, or NULL if an exception is thrown or object is not a function.
    500506*/
    501507JSValueRef JSObjectCallAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argc, JSValueRef argv[], JSValueRef* exception);
     
    514520@param argc An integer count of the number of arguments in argv.
    515521@param argv A JSValue array of the  arguments to pass to the function.
    516 @param exception A pointer to a JSValueRef in which to store an uncaught exception, if any. Pass NULL if you do not care to store an uncaught exception.
    517 @result The JSObject that results from calling object as a constructor, or NULL if an uncaught exception is thrown or object is not a constructor.
     522@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
     523@result The JSObject that results from calling object as a constructor, or NULL if an exception is thrown or object is not a constructor.
    518524*/
    519525JSObjectRef JSObjectCallAsConstructor(JSContextRef context, JSObjectRef object, size_t argc, JSValueRef argv[], JSValueRef* exception);
  • trunk/JavaScriptCore/API/JSValueRef.cpp

    r15428 r15443  
    138138}
    139139
    140 bool JSValueIsInstanceOfConstructor(JSContextRef context, JSValueRef value, JSObjectRef constructor)
     140bool JSValueIsInstanceOfConstructor(JSContextRef context, JSValueRef value, JSObjectRef constructor, JSValueRef* exception)
    141141{
    142142    ExecState* exec = toJS(context);
     
    145145    if (!jsConstructor->implementsHasInstance())
    146146        return false;
    147     bool result = jsConstructor->hasInstance(exec, jsValue);
    148     if (exec->hadException())
    149         exec->clearException();
     147    bool result = jsConstructor->hasInstance(exec, jsValue); // false if an exception is thrown
     148    if (exec->hadException()) {
     149        if (exception)
     150            *exception = toRef(exec->exception());
     151        exec->clearException();
     152    }
    150153    return result;
    151154}
     
    172175}
    173176
    174 bool JSValueToBoolean(JSContextRef context, JSValueRef value, JSValueRef* exception)
    175 {
    176     JSLock lock;
    177     ExecState* exec = toJS(context);
    178     JSValue* jsValue = toJS(value);
    179    
    180     bool boolean = jsValue->toBoolean(exec);
    181     if (exec->hadException()) {
    182         if (exception)
    183             *exception = toRef(exec->exception());
    184         exec->clearException();
    185         boolean = false;
    186     }
    187     return boolean;
     177bool JSValueToBoolean(JSContextRef context, JSValueRef value)
     178{
     179    ExecState* exec = toJS(context);
     180    JSValue* jsValue = toJS(value);
     181    return jsValue->toBoolean(exec);
    188182}
    189183
  • trunk/JavaScriptCore/API/JSValueRef.h

    r15428 r15443  
    146146/*!
    147147@function
    148 @abstract       Tests whether a JavaScript value is an object constructed by
    149  a given constructor, as compared by the JS instanceof operator.
    150 @param context  The execution context to use.
    151 @param value    The JSValue to test.
    152 @param object   The constructor to test against.
    153 @result         true if value is an object constructed by constructor, as compared
    154  by the JS instanceof operator, otherwise false.
    155 */
    156 bool JSValueIsInstanceOfConstructor(JSContextRef context, JSValueRef value, JSObjectRef constructor);
     148@abstract Tests whether a JavaScript value is an object constructed by a given constructor, as compared by the JS instanceof operator.
     149@param context The execution context to use.
     150@param value The JSValue to test.
     151@param object The constructor to test against.
     152@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
     153@result true if value is an object constructed by constructor, as compared by the JS instanceof operator, otherwise false.
     154*/
     155bool JSValueIsInstanceOfConstructor(JSContextRef context, JSValueRef value, JSObjectRef constructor, JSValueRef* exception);
    157156
    158157// Creating values
     
    205204@param context  The execution context to use.
    206205@param value    The JSValue to convert.
    207 @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
    208 @result         The boolean result of conversion, or false if an exception is thrown.
    209 */
    210 bool JSValueToBoolean(JSContextRef context, JSValueRef value, JSValueRef* exception);
     206@result         The boolean result of conversion.
     207*/
     208bool JSValueToBoolean(JSContextRef context, JSValueRef value);
    211209
    212210/*!
     
    236234@param value    The JSValue to convert.
    237235@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
    238 @result         The JSObject result of conversion, or NULL if conversion fails.
     236@result         The JSObject result of conversion, or NULL if an exception is thrown.
    239237*/
    240238JSObjectRef JSValueToObject(JSContextRef context, JSValueRef value, JSValueRef* exception);
  • trunk/JavaScriptCore/API/minidom.c

    r15437 r15443  
    4141   
    4242    JSStringRef printIString = JSStringCreateWithUTF8CString("print");
    43     JSObjectSetProperty(context, globalObject, printIString, JSObjectMakeFunction(context, print), kJSPropertyAttributeNone);
     43    JSObjectSetProperty(context, globalObject, printIString, JSObjectMakeFunction(context, print), kJSPropertyAttributeNone, NULL);
    4444    JSStringRelease(printIString);
    4545   
    4646    JSStringRef node = JSStringCreateWithUTF8CString("Node");
    47     JSObjectSetProperty(context, globalObject, node, JSObjectMakeConstructor(context, JSNode_construct), kJSPropertyAttributeNone);
     47    JSObjectSetProperty(context, globalObject, node, JSObjectMakeConstructor(context, JSNode_construct), kJSPropertyAttributeNone, NULL);
    4848    JSStringRelease(node);
    4949   
  • trunk/JavaScriptCore/API/testapi.c

    r15437 r15443  
    3939static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
    4040{
    41     if (JSValueToBoolean(context, value, NULL) != expectedValue)
     41    if (JSValueToBoolean(context, value) != expectedValue)
    4242        fprintf(stderr, "assertEqualsAsBoolean failed: %p, %d\n", value, expectedValue);
    4343}
     
    106106}
    107107
    108 static bool MyObject_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
     108static bool MyObject_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName)
    109109{
    110110    UNUSED_PARAM(context);
     
    160160        return true;
    161161   
     162    if (JSStringIsEqualToUTF8CString(propertyName, "throwOnDelete")) {
     163        *exception = JSValueMakeNumber(2);
     164        return false;
     165    }
     166
    162167    return false;
    163168}
     
    206211
    207212    JSStringRef numberString = JSStringCreateWithUTF8CString("Number");
    208     JSObjectRef numberConstructor = JSValueToObject(context, JSObjectGetProperty(context, JSContextGetGlobalObject(context), numberString), NULL);
     213    JSObjectRef numberConstructor = JSValueToObject(context, JSObjectGetProperty(context, JSContextGetGlobalObject(context), numberString, NULL), NULL);
    209214    JSStringRelease(numberString);
    210215
    211     return JSValueIsInstanceOfConstructor(context, possibleValue, numberConstructor);
     216    return JSValueIsInstanceOfConstructor(context, possibleValue, numberConstructor, NULL);
    212217}
    213218
     
    218223   
    219224    switch (type) {
    220     case kJSTypeBoolean:
    221         *exception = JSValueMakeNumber(2);
    222         return NULL;
    223225    case kJSTypeNumber:
    224226        return JSValueMakeNumber(1);
     
    288290    if (argc > 0) {
    289291        JSStringRef value = JSStringCreateWithUTF8CString("value");
    290         JSObjectSetProperty(context, result, value, argv[0], kJSPropertyAttributeNone);
     292        JSObjectSetProperty(context, result, value, argv[0], kJSPropertyAttributeNone, NULL);
    291293        JSStringRelease(value);
    292294    }
     
    371373    assert(didInitialize);
    372374    JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
    373     JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone);
     375    JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);
    374376    JSStringRelease(myObjectIString);
    375377   
     
    389391    assert(exception);
    390392   
    391     exception = NULL;
    392     assert(!JSValueToBoolean(context, myObject, &exception));
    393     assert(exception);
     393    assert(JSValueToBoolean(context, myObject));
    394394   
    395395    exception = NULL;
     
    505505   
    506506    JSStringRef array = JSStringCreateWithUTF8CString("Array");
    507     v = JSObjectGetProperty(context, globalObject, array);
     507    v = JSObjectGetProperty(context, globalObject, array, NULL);
    508508    assert(v);
    509509    JSObjectRef arrayConstructor = JSValueToObject(context, v, NULL);
     
    511511    result = JSObjectCallAsConstructor(context, arrayConstructor, 0, NULL, NULL);
    512512    assert(result);
    513     assert(JSValueIsInstanceOfConstructor(context, result, arrayConstructor));
    514     assert(!JSValueIsInstanceOfConstructor(context, JSValueMakeNull(), arrayConstructor));
     513    assert(JSValueIsInstanceOfConstructor(context, result, arrayConstructor, NULL));
     514    assert(!JSValueIsInstanceOfConstructor(context, JSValueMakeNull(), arrayConstructor, NULL));
    515515   
    516516    JSStringRef functionBody;
     
    521521    assert(!JSObjectMakeFunctionWithBody(context, functionBody, NULL, 1, &exception));
    522522    assert(JSValueIsObject(exception));
    523     v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line);
     523    v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line, NULL);
    524524    assert(v);
    525525    assertEqualsAsNumber(v, 2); // FIXME: Lexer::setCode bumps startingLineNumber by 1 -- we need to change internal callers so that it doesn't have to (saying '0' to mean '1' in the API would be really confusing -- it's really confusing internally, in fact)
     
    537537    JSStringRef print = JSStringCreateWithUTF8CString("print");
    538538    JSObjectRef printFunction = JSObjectMakeFunction(context, print_callAsFunction);
    539     JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone);
     539    JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone, NULL);
    540540    JSStringRelease(print);
    541541   
     
    545545    JSStringRef myConstructorIString = JSStringCreateWithUTF8CString("MyConstructor");
    546546    JSObjectRef myConstructor = JSObjectMakeConstructor(context, myConstructor_callAsConstructor);
    547     JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone);
     547    JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL);
    548548    JSStringRelease(myConstructorIString);
    549549   
     
    552552   
    553553    o = JSObjectMake(context, NULL, NULL);
    554     JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(1), kJSPropertyAttributeNone);
    555     JSObjectSetProperty(context, o, jsCFIString,  JSValueMakeNumber(1), kJSPropertyAttributeDontEnum);
     554    JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(1), kJSPropertyAttributeNone, NULL);
     555    JSObjectSetProperty(context, o, jsCFIString,  JSValueMakeNumber(1), kJSPropertyAttributeDontEnum, NULL);
    556556    JSPropertyEnumeratorRef enumerator = JSObjectCreatePropertyEnumerator(o);
    557557    int count = 0;
  • trunk/JavaScriptCore/API/testapi.js

    r15404 r15443  
    5050delete MyObject.cantDelete;
    5151shouldBe("MyObject.cantDelete", 1);
     52shouldBe("delete MyObject.throwOnDelete", 2); // deleteProperty -- should throw 2
    5253MyObject.cantSet = 1;
    5354shouldBe("MyObject.cantSet", undefined);
     
    7374shouldBe("MyObject()", undefined);
    7475shouldBe("typeof new MyObject()", "object");
    75 shouldBe("MyObject ? 1 : 0", 2); // toBoolean -- should throw 2
     76shouldBe("MyObject ? 1 : 0", true); // toBoolean
    7677shouldBe("+MyObject", 1); // toNumber
    7778shouldBe("(MyObject.toString())", "[object CallbackObject]"); // toString
  • trunk/JavaScriptCore/ChangeLog

    r15440 r15443  
     12006-07-14  Geoffrey Garen  <[email protected]>
     2
     3        Reviewed by Maciej.
     4       
     5        - Finalized exception handling in the API.
     6       
     7        setProperty can throw because it throws for built-in arrays. getProperty
     8        and deleteProperty can throw because setProperty can throw and we want
     9        to be consistent, and also because they seem like "actions." callAsFunction,
     10        callAsConstructor, and hasInstance can throw, because they caan throw for
     11        all built-ins.
     12       
     13        toBoolean can't throw because it's defined that way in the spec.
     14       
     15        - Documented that toBoolean and toObject can't be overridden by custom
     16        objects because they're defined that way in the spec.
     17
    118=== Safari-521.17 ===
    219
  • trunk/JavaScriptCore/bindings/objc/objc_runtime.mm

    r15071 r15443  
    305305}
    306306
    307 bool ObjcFallbackObjectImp::toBoolean(ExecState*) const
     307bool ObjcFallbackObjectImp::toBoolean(ExecState *) const
    308308{
    309309    id targetObject = _instance->getObject();
Note: See TracChangeset for help on using the changeset viewer.