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 <[email protected]> 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

Reply via email to