[SERVER-7710] V8 build isn't supporting some stored JavaScript that SpiderMonkey build could handle Created: 19/Nov/12  Updated: 11/Jul/16  Resolved: 08/Mar/13

Status: Closed
Project: Core Server
Component/s: JavaScript
Affects Version/s: None
Fix Version/s: 2.4.0-rc2

Type: Bug Priority: Major - P3
Reporter: Tad Marshall Assignee: Tad Marshall
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Tested using PyMongo driver


Issue Links:
Related
related to SERVER-7705 ReferenceError executing stored JS wi... Closed
Operating System: ALL
Participants:

 Description   

This code works in both SpiderMonkey and V8 builds:

C:\> python
Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymongo
>>> c = pymongo.Connection(port=27999)
>>> db = c.test
>>> db.system_js.foo = "function(){return 5;}"
>>> db.system_js.foo()
5.0

This code works in SpiderMonkey builds but not in V8 builds:

SpiderMonkey

>>> db2.system_js.bar = "return 5;"
>>> db2.system_js.bar()
5.0

V8

>>> db.system_js.bar = "return 5;"
>>> db.system_js.bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\site-packages\pymongo\database.py", line 776, in <lambda>
    scope={'name': name}), *args)
  File "C:\Python27\lib\site-packages\pymongo\database.py", line 716, in eval
    result = self.command("$eval", code, args=args)
  File "C:\Python27\lib\site-packages\pymongo\database.py", line 355, in command
    msg, allowable_errors)
  File "C:\Python27\lib\site-packages\pymongo\helpers.py", line 129, in _check_command_response
    raise OperationFailure(msg % response["errmsg"])
pymongo.errors.OperationFailure: command SON([('$eval', Code('function() { return this[name].apply(this, arguments); }', {'name': 'bar'})), ('args', ())]) failed: invoke failed: error in invoke: _funcs1:1 TypeError: Cannot call method 'apply' of null
_funcs1 = function() { return this[name].apply(this, arguments); }
                                         ^

The V8 server shows this as a "compile" error:

<unknown>:33: Uncaught SyntaxError: Unexpected token return
Mon Nov 19 10:32:38.381 [conn1] Could not compile function: ____MongoToV8_newFunction_temp = return 5;
Mon Nov 19 10:32:38.396 [conn1] error in invoke: _funcs1:1 TypeError: Cannot call method 'apply' of null
_funcs1 = function() { return this[name].apply(this, arguments); }
                                         ^

The way that stored functions are being processed in the V8 build requires them to be assignable as presented, so "function()

{<stuff>}

" works but "<stuff>" doesn't work.



 Comments   
Comment by Ben Becker [ 08/Mar/13 ]

This has been fixed, but I'm not sure which commit fixed this specific issue. Output from v2.4.0-rc2:

>>> import pymongo
>>> c = pymongo.Connection()
>>> db = c.test
>>> db.system_js.foo = "function(){return 5;}"
>>> db.system_js.foo()
5.0

Comment by Daniel Pasette (Inactive) [ 28/Dec/12 ]

Is this behavior we really need to support with v8 or at all?

Comment by Ben Becker [ 19/Dec/12 ]

I stumbled across something similar while going through eval-related js tests, and thought this may be related. V8Scope::__createFunction() checks for hasFunctionIdentifier() and then manipulates the script (as does spidermonkey). In spidermonkey tough, we use isSimpleStatement(), which has different logic.

I'm not in love with either of these functions – they perform several string::find() operations, and don't actually guarantee anything. For example,

    while (true) {}

would be considered a 'simple statement', but:

    while  (true) {}

would not be considered simple (note the two spaces). I think part of this logic is to handle REPL input from the shell, but we may also need it for compatibility in db.eval().

I'm pretty sure there's a better way to handle this; e.g. by using v8::ScriptData::PreCompile() and v8::scriptData::HasError(). See also the drived class 'ScriptDataImpl', which has methods like v8::ScriptDataImpl::GetFunctionEntry(), v8::ScriptDataImpl::symbol_count(), etc.

Generated at Thu Feb 08 03:15:22 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.