Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-78357

Object.entries does not return lazy properties that were not previously resolved for JS Object-BSON/BSONInfo

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Critical - P2 Critical - P2
    • 7.3.0-rc0
    • Affects Version/s: None
    • Component/s: None
    • Query Integration
    • Fully Compatible
    • ALL
    • Hide

       

       

      (function()
      { "use strict"; db.bson_object_entries_bug.drop(); // We want some BSON objects for this test. One convenient way to get that is to insert them // into the database and then get them back through a query. const coll = db.bson_object_entries_bug;assert.commandWorked(coll.insert(\{a: 1, b: 2}
      ));
      let res = coll.findOne();
      assert.eq(["_id", "a", "b"], Object.keys(res))
      // This is wrong! We should see [\{_id: ObjectId(...)}, \{a: 1}, \{b: 1}]
      assert.eq([], Object.entries(res))
      // We can still access the entries via normally property access, both with dots...
      assert.eq(1, res.a);
      //...and brackets
      assert.eq(2, res["b"]);
      // Once we've accessed the entries, they show up in the Object.entries output.
      assert.eq([["a", 1], ["b", 2]], Object.entries(res))
      }()); 
      Show
          (function() { "use strict" ; db.bson_object_entries_bug.drop(); // We want some BSON objects for this test. One convenient way to get that is to insert them // into the database and then get them back through a query. const coll = db.bson_object_entries_bug; assert .commandWorked(coll.insert(\{a: 1, b: 2} )); let res = coll.findOne(); assert .eq([ "_id" , "a" , "b" ], Object .keys(res)) // This is wrong! We should see [\{_id: ObjectId(...)}, \{a: 1}, \{b: 1}] assert .eq([], Object .entries(res)) // We can still access the entries via normally property access, both with dots... assert .eq(1, res.a); //...and brackets assert .eq(2, res[ "b" ]); // Once we've accessed the entries, they show up in the Object .entries output. assert .eq([[ "a" , 1], [ "b" , 2]], Object .entries(res)) }());
    • 146

      Spidermonkey/mozjs has a concept of "lazy properties" for custom Javascript objects defined with JSAPI. When a property is not found in Javascript for some custom object, a hook (the "resolve" function) for that custom object is called to (possibly) load the property into the JS engine.  

      The custom BSON JS object we provide to mozjs uses this feature to implement all of it's properties; each BSON element corresponds to a property of the JS object, but the properties are loaded into JS lazily as needed through calls to the "BSONInfo::resolve" function defined here . Similarly, the enumerable property keys (not values; just the names of the properties) are provided to the JS engine via the "BSONInfo::enumerate" function.

      This works when properties are accessed on the objects in JS, and all of the keys are correctly visible in JS via Object.keys. However, the Object.entries function excludes the key/value pair for any property that wasn't already resolved into JS by previous property lookup. See the reproduction script for specifics.

      The issue appears to be due to the fact that the mozjs implementation of the Object.entries is not calling the resolve function for unresolved properties. Reading the code, I couldn't figure out why, as it appears to be attempting to. It's unclear to me if it needs to, though, or if the enumerate function is required to previously have resolved all lazy properties into the engine. 

      We need to figure out if enumerate should be doing this work + load the values into JS there if needed, or determine the root-cause of this issue if not. 

       

      A workaround in the meanwhile is to simply to Object.assign to copy the BSON-object into an empty object before using Object.entries, which will resolve all lazy properties.  for..in can also be used instead of Object.entries as it forces property resolution correctly. 

            Assignee:
            santiago.roche@mongodb.com Santiago Roche
            Reporter:
            george.wangensteen@mongodb.com George Wangensteen
            Votes:
            3 Vote for this issue
            Watchers:
            16 Start watching this issue

              Created:
              Updated:
              Resolved: