Skip to content

Loading…

Bug with JSCore multiple typemap out values and JSObjectMakeArray #42

Open
ewmailing opened this Issue · 0 comments

1 participant

@ewmailing

I found a bug with the way multiple return values are handled with the JSCore implementation.

Basically, I have this function that takes 5 parameters where arg2-5 are out-values. (The function also returns an int value.)
result = (int)SDL_QueryTexture(arg1,arg2,arg3,arg4,arg5);

The implementation tries to put all the out-value arguments into an array to pass back.
The problem arises in the first step and how SWIGJSC_AppendOutput works.

Below is an excerpt from the generated code.
1) Note that the return value is first put into the jsresult.
2) Then SWIGJSC_AppendOutput passes jsresult as a parameter with the expectation that that the function will return a new array containing both objects
3) Then SWIGJSC_AppendOutput is used again to keep appending arguments.

static JSValueRef _wrap_QueryTexture(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception)
{
...

result = (int)SDL_QueryTexture(arg1,arg2,arg3,arg4,arg5);
jsresult = SWIG_From_int SWIG_JSC_FROM_CALL_ARGS((int)(result));
if (SWIG_IsTmpObj(res2)) {
jsresult = SWIGJSC_AppendOutput(context, jsresult, SWIG_From_int SWIG_JSC_FROM_CALL_ARGS((arg2)));
} else {
int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ;
jsresult = SWIGJSC_AppendOutput(context, jsresult, SWIG_NewPointerObj((void
)(arg2), SWIGTYPE_p_unsigned_int, new_flags));
}
if (SWIG_IsTmpObj(res3)) {
jsresult = SWIGJSC_AppendOutput(context, jsresult, SWIG_From_int SWIG_JSC_FROM_CALL_ARGS((arg3)));
} else {
int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ;
jsresult = SWIGJSC_AppendOutput(context, jsresult, SWIG_NewPointerObj((void
)(arg3), SWIGTYPE_p_int, new_flags));
...
return jsresult;
goto fail;
}

The problem is that it is not possible for SWIGJSC_AppendOutput to distinguish between an array and some other object. This code won't work:

if (JSValueIsUndefined(context, value)) {
arr = JSObjectMakeArray(context, 0, 0, 0);
} else {
arr = JSValueToObject(context, value, 0);
}

The problem is that the first return value is not a JSUndefined. It is actually an object (a number object for the int return value in this specific case).

To further complicate things, it doesn't seem possible to distinguish between an array vs. any other JSObjectRef in the JSCore API. It looks like you are expected to implement your own conventions if you need it.

http://stackoverflow.com/questions/23387613/how-to-check-if-the-jsobjectref-object-is-an-array

Anyway, I'm not sure what the best solution is, but my initial thought is that instead of trying to use SWIGJSC_AppendOutput to both create-the-array-if-necessary and append the array, the generated calling code should create the array (if there will be multiple parameters). So the generated code will look like this instead:

result = (int)SDL_QueryTexture(arg1,arg2,arg3,arg4,arg5);
// create the array here

jsresult = JSObjectMakeArray(context, 0, 0, 0);
// put the result in the array

jsresult = SWIGJSC_AppendOutput(context, jsresult, SWIG_From_int SWIG_JSC_FROM_CALL_ARGS((int)(result)));
// same as before

if (SWIG_IsTmpObj(res2)) {
jsresult = SWIGJSC_AppendOutput(context, jsresult, SWIG_From_int SWIG_JSC_FROM_CALL_ARGS((arg2)));
} else {
int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0 ) : 0 ;
jsresult = SWIGJSC_AppendOutput(context, jsresult, SWIG_NewPointerObj((void
)(arg2), SWIGTYPE_p_unsigned_int, new_flags));
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.