[webkit-dev] Optional parameter in IDL and undefined JS value

Anton Muhin antonm at chromium.org
Wed Apr 20 22:14:57 PDT 2011


Just my two cents.

There is an elaborate specification how Array.prototype.slice should
treat undefined parameters, see ECMAScript 5, 15.4.4.10.  Please, note
that the spec treats undefined start and end differently: start is
converted with ToInteger which turns undefined into 0, while end is
treated as len if it's undefined.

Alas, we don't have such an elaborate spec for DOM methods.  I
personally find different behaviour of foo() vs. foo(undefined)
somewhat counterintuitive, but technically one can use
arguments.length to implement such a dispatch in pure JS, so IMHO it's
fine (cf. though with Array.slice which doesn't use arguments.length
and AFAIK no other functions in ECMAScript, at least not one for
arrays.)

yours,
anton.

On Wed, Apr 20, 2011 at 9:37 PM, Jian Li <jianli at chromium.org> wrote:
> I am referring to Blob.slice(start, end) that mimics Array.slice. Where in
> WebIDL has this behavior defined? Sorry I can't find it in the spec.
> For Array.slice(start, end), both Safari and Chrome treat passing undefined
> as omitted parameter, while Firefox and IE treat passing undefined as 0. If
> it is true that passing undefined should be treated as 0, we do not have a
> bug in JSC and V8 bindings layer. However, we do have a bug in JSC and V8
> internals.
>
> On Wed, Apr 20, 2011 at 7:28 PM, Maciej Stachowiak <mjs at apple.com> wrote:
>>
>> On Apr 20, 2011, at 6:16 PM, Jian Li wrote:
>>
>> Hi,
>> I've just found a problem in our generated code for handling optional
>> parameters. Suppose we define a method with optional parameter in numeric
>> type, like the following in IDL:
>>          Foo bar(in [Optional] long long start, in [Optional] long long
>> end);
>> And we declare our C++ method as the following. Note that the default
>> value of the 2nd parameter is not 0.
>>          PassRefPtr<Foo> bar(long long start = 0, long long end =
>> std::numeric_limits<long long>::max());
>> If we call the JS method with only 1 parameter, everything works as
>> expected. However, if we call the JS method with 2 parameters and pass
>> 'undefined' as the 2nd parameter, we trigger the problem.
>>
>> Is it actually a bug that explicitly passing undefined acts like passing
>> 0, instead of like an omitted parameter? I think it's correct per Web IDL.
>> What's the specific case where this is a problem?
>> Regards,
>> Maciej
>>
>> By looking into the generated JSC code below, I found out that we are
>> converting undefined JS value to 0 and pass it to the function. As the
>> result, the default parameter value in the declaration is not respected.
>>
>> EncodedJSValue JSC_HOST_CALL jsFooPrototypeFunctionFoo(ExecState* exec)
>> {
>>     JSValue thisValue = exec->hostThisValue();
>>     if (!thisValue.inherits(&JSFoo::s_info))
>>         return throwVMTypeError(exec);
>>     JSFoo* castedThis = static_cast<JSFoo*>(asObject(thisValue));
>>     Foo* imp = static_cast<Foo*>(castedThis->impl());
>>     int argsCount = exec->argumentCount();
>>     if (argsCount <= 0) {
>>         JSC::JSValue result = toJS(exec, castedThis->globalObject(),
>> WTF::getPtr(imp->bar()));
>>         return JSValue::encode(result);
>>     }
>>     long long start(static_cast<long
>> long>(exec->argument(0).toInteger(exec)));
>>     if (exec->hadException())
>>         return JSValue::encode(jsUndefined());
>>     if (argsCount <= 1) {
>>         JSC::JSValue result = toJS(exec, castedThis->globalObject(),
>> WTF::getPtr(imp->bar(start)));
>>         return JSValue::encode(result);
>>     }
>>     long long end(static_cast<long
>> long>(exec->argument(1).toInteger(exec)));
>>     if (exec->hadException())
>>         return JSValue::encode(jsUndefined());
>>     JSC::JSValue result = toJS(exec, castedThis->globalObject(),
>> WTF::getPtr(imp->bar(start, end)));
>>     return JSValue::encode(result);
>> }
>>
>> One solution is to add the default value support in IDL. For example, we
>> can change the above definition of bar to something like:
>>          Foo bar(in [Optional, DefaultValue=0] long long start, in
>> [Optional, DefaultValue=2147483647] long long end);
>> Or the other way is to add a bool parameter for each optional parameter in
>> the class method declaration, that is used to indicate if the passing
>> parameter is defined or not. This would involve the change to both code
>> generator scripts and the existing implementations.
>> How do you think? Personally I like the 1st approach since it is simpler.
>> Thanks,
>> Jian
>>
>> _______________________________________________
>> webkit-dev mailing list
>> webkit-dev at lists.webkit.org
>> http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
>>
>
>
> _______________________________________________
> webkit-dev mailing list
> webkit-dev at lists.webkit.org
> http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
>
>


More information about the webkit-dev mailing list