You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@couchdb.apache.org by Paul Davis <pa...@gmail.com> on 2009/04/08 17:30:16 UTC

Re: differences in the "instanceof" operation between CouchDB View and couchjs.

On Wed, Apr 8, 2009 at 8:49 AM, Yohei Sasaki <ys...@gmail.com> wrote:
> Hi all,
>
> I came across a problem in my view script with the "instanceof" operation.
> Can anyone explain the cause of my problem duplicated by following steps?
>
> ===
> 1. Add a document with an Array member into a database.
>
> {
>  "_id": "oh_my_array",
>  "_rev": "2-3397837489",
>  "array_member": [
>      1,
>      2,
>      3
>  ]
> }
>
> 2. Run the following map-only view.
>
> function(doc) {
>  emit("0_raw_data", doc.array_member);
>  emit("1_instanceof", (doc.array_member instanceof Array));
>  emit("2_constructor.name", doc.array_member.constructor.name);
>  emit("3_typeof", (typeof doc.array_member));
> }
>
> 3. Get the strange value in "1_instanceof" in Futon.
>
> (key, value) ->
> ("0_raw_data", [1,2,3])
> ("1_instanceof", false);                         <-- why not true?
> ("2_constructor.name", "Array");
> ("3_typeof", "object");
> ===
> # As above, "constructor.name" is an workaround instead of instanceof.
>
> So I don't know why "instanceof" operation returns false for the array
> value.
> # This means we cannot use the instanceof operation for condtion expressions
> such as  if(  a instanceof Array){ ... }
>
> BTW, I use CouchDB 0.9.0 (installed from the tarball on Apache) with JS
> 1.7(installed from MacPorts).
> And on couchjs standalone mode, the expression, 'instanceof Array'
> returns true as follows:
>
> ===
> mac:~ yssk22$ cat a.js
> var doc = {
>  "_id": "oh_my_array",
>  "_rev": "2-3397837489",
>  "array_member": [
>      1,
>      2,
>      3
>  ]
> };
> print(doc.array_member instanceof Array);
>
> mac:~ yssk22$ /usr/local/bin/couchjs a.js
> true
> ===
>
> Thanks.
>
> --
> Yohei SASAKI
> http://github.com/yssk22/
>

My first guess is that this is an artifact of the sandbox that view
functions run in. Since the JS_Context* that is used for running the
functions is never initialized with JS_InitStandardClasses the Array
class isn't defined and as such you can't test if the object is an
instance.

IIRC, JS_InitStandardClasses has a fairly pricey runtime cost
associated with it so I doubt calling it on all sand box contexts
would be the way to go. Perhaps with some refactoring of couchjs to
make sure that its called optionally, and only once per view update
wouldn't be out of the question. Patches welcome.

HTH,
Paul Davis

Re: differences in the "instanceof" operation between CouchDB View and couchjs.

Posted by Yohei Sasaki <ys...@gmail.com>.
Hi Paul,

sorry for my late response.
Your advice was very helpful, but I have not resolve the problem.

As you wrote, It is exactly true that JS_InitStandardClasses may or  
may not be called in the view sandbox runtime.
So I modified couch_js for JS_InitStandardClasses to be called for  
sure as follows

  221         sandbox = JS_NewObject(sub_context, NULL, NULL, NULL);
  222         // if (!sandbox || !JS_InitStandardClasses(sub_context,  
sandbox)) {
  223         if (!JS_InitStandardClasses(sub_context, sandbox)) {

And I tried the view but the result did not change.
I'm not familiar with jsapi in SpiderMonkey so that I tried another  
view as follows:

function(doc) {
  emit("0_Array", Array.toString());
  emit("1_Number", Number.toString());
  emit("2_Is Array?",  doc.array_member    instanceof Array)
  emit("3_Is Number?", doc.array_member[1] instanceof Number)
  // test the user  class
  TestClass = function(){};
  var obj = new TestClass();
  emit("4_InstanceOfUserClass", obj instanceof TestClass)
}

got the result:

(key, value) ->
("0_Array", "function Array() {\n [native code]\n}")
("1_Number", "function Number() {\n [native code]\n}")
("2_Is Array", false)
("3_Is Number", false)
("4_InstanceOfUserClass", true)

So only native classes such as Array or Number seem to be defined, for  
which instanceof operation does not work.

I'll examine the behavior of "instanceof" (JS_InstanceOf API?)  in  
SpiderMonkey....

--
Yohei Sasaki
http://github.com/yssk22/


On 2009/04/09, at 0:30, Paul Davis wrote:

> On Wed, Apr 8, 2009 at 8:49 AM, Yohei Sasaki <ys...@gmail.com> wrote:
>> Hi all,
>>
>> I came across a problem in my view script with the "instanceof"  
>> operation.
>> Can anyone explain the cause of my problem duplicated by following  
>> steps?
>>
>> ===
>> 1. Add a document with an Array member into a database.
>>
>> {
>>  "_id": "oh_my_array",
>>  "_rev": "2-3397837489",
>>  "array_member": [
>>      1,
>>      2,
>>      3
>>  ]
>> }
>>
>> 2. Run the following map-only view.
>>
>> function(doc) {
>>  emit("0_raw_data", doc.array_member);
>>  emit("1_instanceof", (doc.array_member instanceof Array));
>>  emit("2_constructor.name", doc.array_member.constructor.name);
>>  emit("3_typeof", (typeof doc.array_member));
>> }
>>
>> 3. Get the strange value in "1_instanceof" in Futon.
>>
>> (key, value) ->
>> ("0_raw_data", [1,2,3])
>> ("1_instanceof", false);                         <-- why not true?
>> ("2_constructor.name", "Array");
>> ("3_typeof", "object");
>> ===
>> # As above, "constructor.name" is an workaround instead of  
>> instanceof.
>>
>> So I don't know why "instanceof" operation returns false for the  
>> array
>> value.
>> # This means we cannot use the instanceof operation for condtion  
>> expressions
>> such as  if(  a instanceof Array){ ... }
>>
>> BTW, I use CouchDB 0.9.0 (installed from the tarball on Apache)  
>> with JS
>> 1.7(installed from MacPorts).
>> And on couchjs standalone mode, the expression, 'instanceof Array'
>> returns true as follows:
>>
>> ===
>> mac:~ yssk22$ cat a.js
>> var doc = {
>>  "_id": "oh_my_array",
>>  "_rev": "2-3397837489",
>>  "array_member": [
>>      1,
>>      2,
>>      3
>>  ]
>> };
>> print(doc.array_member instanceof Array);
>>
>> mac:~ yssk22$ /usr/local/bin/couchjs a.js
>> true
>> ===
>>
>> Thanks.
>>
>> --
>> Yohei SASAKI
>> http://github.com/yssk22/
>>
>
> My first guess is that this is an artifact of the sandbox that view
> functions run in. Since the JS_Context* that is used for running the
> functions is never initialized with JS_InitStandardClasses the Array
> class isn't defined and as such you can't test if the object is an
> instance.
>
> IIRC, JS_InitStandardClasses has a fairly pricey runtime cost
> associated with it so I doubt calling it on all sand box contexts
> would be the way to go. Perhaps with some refactoring of couchjs to
> make sure that its called optionally, and only once per view update
> wouldn't be out of the question. Patches welcome.
>
> HTH,
> Paul Davis