Broken property access on objects from other contexts?

Ryan Berdeen rberdeen at hubspot.com
Thu Mar 9 21:10:13 UTC 2017


I'm running into an issue passing plain JS objects to a function created
with loadWithNewGlobal. I didn't expect property access to behave
differently on objects from other contexts, but the behavior when using
numeric keys seems broken.

Is there a safe way to pass objects between contexts so that the property
access semantics don't change?

I wrote a simple test script. It creates a function with a new global that
is simply o[i] = o[i]. If the key (once converted to a string) exists in o,
this shouldn't change the value in o.

    var reassignNewGlobal = loadWithNewGlobal({
      script: '(function (o, i) { o[i] = o[i]; })',
      name: 'test.js'
    });

    function test(i) {
      var o = {};
      o[i] = true;
      o[i] = o[i];
      print('expected: ' + JSON.stringify(o));
      reassignNewGlobal(o, i);
      print('actual:   ' + JSON.stringify(o));
      print();
    }

    test(-2147483649);
    test(-2147483648);
    test(2147483647);
    test(2147483648);

Running this, I get

expected: {"-2147483649":true}
actual:   {"-2147483649":true,"-1":null}

expected: {"-2147483648":true}
actual:   {"-2147483648":null}

expected: {"2147483647":true}
actual:   {"2147483647":true}

expected: {"2147483648":true}
actual:   {"2147483648":true,"-1":null}

There are a few strange things here:
* The issue that broke my actual application, which is that you can't read
properties with names outside the range of int
* Setting a property with a name outside the range of int actually sets a
property named "-1"
* You can't get properties with negative names, but you can set them
* When the value is missing due to one of the above, null is returned
rather than undefined

Debugging through this, it looked like the logic driving this is
in JSObjectLinker get/put, but I couldn't tell from there if this behavior
was intentional or a bug. I would expect keys to be converted to strings
except when the target is an array, but it instead seems based on whether
they key is an int or a long.

I tested tested this with with the Oracle JRE 1.8.0_66-b17 and 9-ea+158.

Thanks!

Ryan


More information about the nashorn-dev mailing list