Broken property access on objects from other contexts? (original) (raw)

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:

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