JavaScript Changes in MongoDB 2.4

Consider the following impacts of V8 JavaScript Engine in MongoDB 2.4:

Tip

Use the new interpreterVersion() method in the mongo shell and the javascriptEngine field in the output of db.serverBuildInfo() to determine which JavaScript engine a MongoDB binary uses.

Improved Concurrency

Previously, MongoDB operations that required the JavaScript interpreter had to acquire a lock, and a single mongod could only run a single JavaScript operation at a time. The switch to V8 improves concurrency by permitting multiple JavaScript operations to run at the same time.

Modernized JavaScript Implementation (ES5)

The 5th edition of ECMAscript , abbreviated as ES5, adds many new language features, including:

With V8, MongoDB supports the ES5 implementation of Javascript with the following exceptions.

Note

The following features do not work as expected on documents returned from MongoDB queries:

  • Object.seal() throws an exception on documents returned from MongoDB queries.
  • Object.freeze() throws an exception on documents returned from MongoDB queries.
  • Object.preventExtensions() incorrectly allows the addition of new properties on documents returned from MongoDB queries.
  • enumerable properties, when added to documents returned from MongoDB queries, are not saved during write operations.

See SERVER-8216 , SERVER-8223 , SERVER-8215 , and SERVER-8214 for more information.

For objects that have not been returned from MongoDB queries, the features work as expected.

Removed Non-Standard SpiderMonkey Features

V8 does not support the following non-standard SpiderMonkey JavaScript extensions, previously supported by MongoDB’s use of SpiderMonkey as its JavaScript engine.

E4X Extensions

V8 does not support the non-standard E4X extensions. E4X provides a native XML object to the JavaScript language and adds the syntax for embedding literal XML documents in JavaScript code.

You need to use alternative XML processing if you used any of the following constructors/methods:

  • XML()
  • Namespace()
  • QName()
  • XMLList()
  • isXMLName()

Destructuring Assignment

V8 does not support the non-standard destructuring assignments. Destructuring assignment “extract[s] data from arrays or objects using a syntax that mirrors the construction of array and object literals.” - Mozilla docs

Example

The following destructuring assignment is invalid with V8 and throws a SyntaxError:

original = [4, 8, 15];
var [b, ,c] = a;  // <== destructuring assignment
print(b) // 4
print(c) // 15

Iterator(), StopIteration(), and Generators

V8 does not support Iterator(), StopIteration(), and generators .

InternalError()

V8 does not support InternalError(). Use Error() instead.

for each...in Construct

V8 does not support the use of for each…in construct. Use for (var x in y) construct instead.

Example

The following for each (var x in y) construct is invalid with V8:

var o = { name: 'MongoDB', version: 2.4 };

for each (var value in o) {
  print(value);
}

Instead, in version 2.4, you can use the for (var x in y) construct:

var o = { name: 'MongoDB', version: 2.4 };

for (var prop in o) {
  var value = o[prop];
  print(value);
}

You can also use the array instance method forEach() with the ES5 method Object.keys():

Object.keys(o).forEach(function (key) {
  var value = o[key];
  print(value);
});

Array Comprehension

V8 does not support Array comprehensions .

Use other methods such as the Array instance methods map(), filter(), or forEach().

Example

With V8, the following array comprehension is invalid:

var a = { w: 1, x: 2, y: 3, z: 4 }

var arr = [i * i for each (i in a) if (i > 2)]
printjson(arr)

Instead, you can implement using the Array instance method forEach() and the ES5 method Object.keys() :

var a = { w: 1, x: 2, y: 3, z: 4 }

var arr = [];
Object.keys(a).forEach(function (key) {
  var val = a[key];
  if (val > 2) arr.push(val * val);
})
printjson(arr)

Note

The new logic uses the Array instance method forEach() and not the generic method Array.forEach(); V8 does not support Array generic methods. See Array Generic Methods for more information.

Multiple Catch Blocks

V8 does not support multiple catch blocks and will throw a SyntaxError.

Example

The following multiple catch blocks is invalid with V8 and will throw "SyntaxError: Unexpected token if":

try {
  something()
} catch (err if err instanceof SomeError) {
  print('some error')
} catch (err) {
  print('standard error')
}

Conditional Function Definition

V8 will produce different outcomes than SpiderMonkey with conditional function definitions .

Example

The following conditional function definition produces different outcomes in SpiderMonkey versus V8:

function test () {
   if (false) {
      function go () {};
   }
   print(typeof go)
}

With SpiderMonkey, the conditional function outputs undefined, whereas with V8, the conditional function outputs function.

If your code defines functions this way, it is highly recommended that you refactor the code. The following example refactors the conditional function definition to work in both SpiderMonkey and V8.

function test () {
  var go;
  if (false) {
    go = function