-
Notifications
You must be signed in to change notification settings - Fork 850
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ref. mozilla#780 fix Object.assign() when there's a prototype #1242
Conversation
… the case where the target object inherits from a prototype that already contains the property being set
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me - many thanks.
Have tested your fix with HtmlUnit also and all test passing.
Test262SuiteTest also passes as expected without no new tests passing - from my point of view this is also expected because the issue was also not detected by this suite.
I'm sorry that I haven't touched this yet. I have actually looked at it a few times and I'm worried about introducing such a specific test so deep in the "putImpl" method, which is a very hot code path, and one that is already complicated enough. The abstract thing that that particular method already does is pretty hard to define and I fear that this makes it harder. Is there a change that we could make either in the Object.assign code, or in the "AbstractEcmaOperations" class that would be still in keeping with the spec but which would not cause us to have to change something so fundamental. I don't know who might be depending on the existing behavior but given how many things depend on Rhino I fear that it might be a lot of things. |
It's a fair point, @gbrail -- I'm perhaps even more concerned now that you, a primary author on this project, are concerned -- I'm far from an expert on this codebase, and I arrived at this change after writing those I can look at it again from a different perspective, as you suggest. I'm sure you read it already, but I feel like I described what I believe to be the bug to the best of my ability at #780 (comment) I don't know, @tuchida, if you're able to look at I suppose one way to fix this in class AbstractEcmaObjectOperations {
// ...
static void put(Context cx, Scriptable o, String p, Object v, boolean isThrow) {
Scriptable base = ScriptableObject.getBase(o, p);
if (base == null) base = o;
if (base instanceof ScriptableObject) {
ScriptableObject baseObject = (ScriptableObject) base;
// -- START OF NEW CODE --
if (o instanceof ScriptableObject
&& baseObject != o
// -- NEW FUNCTION in ScriptableObject
// that gets the slot and checks if
// it's not null, not read-only, and
// a value slot --
&& baseObject.isWriteableValueSlot(p, 0, isThrow)) {
// If base is not the Receiver (start) object
// and if the slot is a Writeable data descriptor
// then invoke putImpl() on the Receiver (start) object
((ScriptableObject) o).putImpl(p, 0, o, v, isThrow);
} else {
// -- END OF NEW CODE --
baseObject.putImpl(p, 0, o, v, isThrow);
}
} else {
base.put(p, o, v);
}
}
// ...
} Would that be a route worth pursuing, @gbrail and @tuchida ? It would have to be done in both |
While I understand @gbrail concerns, I wonder if the issue we're trying to solve here is limited to scenario's where Object.assign is used (meaning whether it makes sense to see if a fix could be tied exclusively to the Object.assign impl.) or whether there are tests that can be written that trigger the issue while not using Object.assign As for putting it inside the AbstractEcmaObjectOperations.put() implementation: besides that method then not following the spec closely, IMHO it would make the overall All that said: I do understand the concerns about making changes to something so deep in the engine, so we need to be carefull about it, but IMHO if its the best place to do it, we just have to bite the bullit... |
Sorry I'm making this complicated, but that's a really common place. What if we were to implement an "AbstractEcmaOperations.set" method that closely followed the "[[Set]]" specification to the letter. Would that fix Object.assign? Otherwise, I'd be more comfortable fixing this in Object.assign until we understand better what our options might be. |
Should I work on my proposed solution from #1242 (comment) then? |
Hopefully i have some time on this weekend to have a look at all the Rhino stuff in the queue - sorry |
As always i agree with @gbrail concerns but this time it's the other way around - this issue is about something that was broken by the fix/improvement we made. We did not notice that but at least the HtmlUnit test suite shows that we broke the existing behavior. So this fix is about bringing back the old behavior.... |
Did some looking: this works as expected:
And this doesn't:
Both
And I think the key difference is that when doing Object.assign, the logic that is in ScriptableObject.put (that checks the return value of putImpl and if false calls start.put) and that would get called when doing I've locally quickly added code that is missed and ran the test and with the changes in place it yields the correct result:
Whether this is the correct and a complete fix I don't know, just quickly analysed the codepaths and ran a quick test BTW: looking at the AbstractEcmaObjectOperations.put method, I also wonder if the |
fix taken from p-bakker's sugestion
fix taken from p-bakker's sugestion
…0917 * commit '6387bac4281ba1c4a8050cd055071615593d214c': (78 commits) More consistent test optimization levels (mozilla#1317) ci: set minimal permissions on GitHub Workflows Compare all primitive value type wrappers by value Fixing formatting issues Treat String, ConsString, Boolean, and Double as value types setter function (from property descriptor) has to convert the args (see HtmlUnit#7) also use try-with-resource FIX: Wrap key and value for NativeJavaMap iterator Added more tests FIX: Wrap result of iterator BUG: for X of javaList does not work properly in strict mode removed obsolete LineSeparator Spotless Preserving cause, when a JavaException is rethrown in JavaScript fix ScriptException when bound functions are called inside Promise.then() test cases from mozilla#1242 fix taken from p-bakker's sugestion fix name property for bound functions (see issue mozilla#1297) Fix the condition for isResourceChanged Code Cleanup (mozilla#1295) ignore %c styling but count to not disturb further replacements ... # Conflicts: # src/org/mozilla/javascript/NativeObject.java # testsrc/org/mozilla/javascript/tests/json/JsonParserTest.java
Fix Object.assign() -- and [[Set]] in general -- for the case where the target object inherits from a prototype that already contains the property being set
Closes #780, #1195