Skip to content
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

fix missing scope definition at some places #1227

Merged
merged 4 commits into from
May 27, 2022
Merged

Conversation

rbri
Copy link
Collaborator

@rbri rbri commented May 21, 2022

next try to fix #934 (this replaces #1226)

@p-bakker
Copy link
Collaborator

LGTM

@tuchida
Copy link
Contributor

tuchida commented May 22, 2022

Thanks! Looking good for now.

However, I felt that using parentScope here was not a good idea.

var f = function() {};
f.prototype.__parent__; // null before fix, [object global] after
f.prototype.__parent__ = null;
Object.getOwnPropertyDescriptor(f.prototype, 'constructor').hasOwnProperty('value'); // TypeError

This Pull Request is correct and necessary, but it may be better not to use parentScope apart from that. Since scope is used to get TopLevel.Builtins.Object, it looks to me like cx.topCallScope is sufficient.

@rbri
Copy link
Collaborator Author

rbri commented May 22, 2022

Since scope is used to get TopLevel.Builtins.Object, it looks to me like cx.topCallScope is sufficient.

@tuchida Not sure i got your point - do you talk about

obj.setParentScope(getParentScope()); 

inside setupDefaultPrototype()?

@tuchida
Copy link
Contributor

tuchida commented May 22, 2022

This approach also seems to solve the problem.

diff --git a/src/org/mozilla/javascript/ScriptableObject.java b/src/org/mozilla/javascript/ScriptableObject.java
index 46e5aaeb..f1f45a24 100644
--- a/src/org/mozilla/javascript/ScriptableObject.java
+++ b/src/org/mozilla/javascript/ScriptableObject.java
@@ -2651,8 +2651,7 @@ public abstract class ScriptableObject
     protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) {
         Slot slot = querySlot(cx, id);
         if (slot == null) return null;
-        Scriptable scope = getParentScope();
-        return slot.getPropertyDescriptor(cx, (scope == null ? this : scope));
+        return slot.getPropertyDescriptor(cx, cx.topCallScope);
     }
 
     protected Slot querySlot(Context cx, Object id) {

@rbri
Copy link
Collaborator Author

rbri commented May 22, 2022

@tuchida ok, is see, will test and add a commit

@p-bakker
Copy link
Collaborator

If we're deriving the scope from the context, there's not much point in passing it into slot getPropertyas we're also passing in context, no?

But are we 100% sure that it is always correct to read the top level scope from the context and not derive it from the Scriptable?

@rbri
Copy link
Collaborator Author

rbri commented May 22, 2022

If we're deriving the scope from the context, there's not much point in passing it into slot getPropertyas we're also passing in context, no?

Have seen this but i was not sure if we should stay with the signature for backward compatibility.

But are we 100% sure that it is always correct to read the top level scope from the context and not derive it from the Scriptable?

Had the same question in mind but as long we have no test case that proves this i think both solutions are correct - so i did the commit because the code is simpler (from my point of view).

@p-bakker
Copy link
Collaborator

Had the same question in mind but as long we have no test case that proves this i think both solutions are correct - so I did the commit because the code is simpler (from my point of view).

The testcases might be in test262, but not enabled/failing as we're missing part of the required testing infrastructure, see #1077

In the browser I can test the cross-realm scripting using iframes:

// Comparing the __proto__ of a property descriptor of an object from another realm with one from the current realm.
// Yields false, as the the frame ('myframe') has it's own instances of all the global JavaScript objects, like `Object`
let realm = window.myframe;
realm.Object.getOwnPropertyDescriptor(realm.Object, 'getOwnPropertyDescriptor').__proto__ === ({}).__proto__;

realm = window;
// Same check as before, but now all within the same realm, yields true
realm.Object.getOwnPropertyDescriptor(realm.Object, 'getOwnPropertyDescriptor').__proto__ === ({}).__proto__;

The above 'testcase' indicates (I think) that in EcmaScript the lookup of the instance of Object to use for creating for example property descriptors should be based not on the Object instance of the current realm, but on scope in which the object is created on which the getOwnPropertyDescriptor method is called.

The following code with Rhino behaves differently when using cx.topCallScope vs. using the scriptable as scope:

      Context ctx = Context.enter();
      ctx.setLanguageVersion(200);
      Scriptable scriptable = ctx.initStandardObjects();
      Scriptable realm = ctx.initStandardObjects();
      scriptable.put("realm", scriptable, realm);

      String expression = """
        realm.Object.getOwnPropertyDescriptor(realm.Object, 'getOwnPropertyDescriptor').__proto__ === ({}).__proto__;
      """;
      Object result = ctx.evaluateString(scriptable, expression, "<cmd>", 0, null);

      System.out.println(result);

@p-bakker
Copy link
Collaborator

Created a (draft) PR for adding the missing infr, see #1229

@p-bakker
Copy link
Collaborator

The codechange that @tuchida proposed in #1227 (comment) (using return slot.getPropertyDescriptor(cx, cx.topCallScope); wasn't the correct one, but I think the code in that area can be simplified: the getParentScope() call can be removed and instead just call return slot.getPropertyDescriptor(cx, this);

@rbri
Copy link
Collaborator Author

rbri commented May 24, 2022

I think we really have to squash the commits for this pr :->

@p-bakker
Copy link
Collaborator

LGTM now

@rbri rbri requested a review from gbrail May 24, 2022 16:16
Copy link
Collaborator

@gbrail gbrail left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM for me as well. Thanks for tracking this down!

@gbrail gbrail merged commit 7a94441 into mozilla:master May 27, 2022
@rbri rbri deleted the ensure_scope branch May 28, 2022 07:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement ES2017 Object.getOwnPropertyDescriptors
4 participants