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

Implement Display for Objects #171

Closed

Conversation

IovoslavIovchev
Copy link
Contributor

@IovoslavIovchev IovoslavIovchev commented Oct 19, 2019

NB: Due to the fact that the main binary uses the dbg! macro, pretty printing, while present, does not the make output, well.. pretty (e.g. new lines are rendered as \n).

@IovoslavIovchev IovoslavIovchev changed the title WIP: Started implementing Display for Objects Implement Display for Objects Oct 19, 2019
@IovoslavIovchev
Copy link
Contributor Author

#170

@jasonwilliams
Copy link
Member

jasonwilliams commented Oct 19, 2019

This may be out of scope for your PR, but be weary of circular references.
Printing an object A which has a property B which has a property back to A I think causes an infinite loop.

Or at least it did when I was playing with it.
JS naturally has a lot of circular references, so you may want to think how you show properties

@IovoslavIovchev
Copy link
Contributor Author

This implementation indeed does not take circular dependencies into consideration.

I believe I have an idea how that can be achieved, so I will take some more time to look into it and deliver everything in one PR.

@IovoslavIovchev
Copy link
Contributor Author

@jasonwilliams could you take a look?

@IovoslavIovchev
Copy link
Contributor Author

I decided to not filter out the prototype slot, as I still have not found a scenario which causes a stack overflow.
I propose we leave it as is, and if needed, remove it later.

Copy link
Member

@jasonwilliams jasonwilliams left a comment

Choose a reason for hiding this comment

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

Looks good

@jasonwilliams
Copy link
Member

Do we want to somehow share this logic with console.log https://github.com/jasonwilliams/boa/blob/master/src/lib/js/console.rs ?

@IovoslavIovchev
Copy link
Contributor Author

We definitely could do that, only we need to find a way to escape code duplication for printing properties.

@jasonwilliams
Copy link
Member

jasonwilliams commented Oct 22, 2019

@IovoslavIovchev Not sure if you're aware but the newlines aren't being parsed
This is the output i get

[src/bin/bin.rs:57] exec(&buffer) = "{\n\n    __proto__: {\n        valueOf: function() { [native code] },\n        constructor: {\n            prototype: \'[Cycle]\'\n            call: function() { [native code] },\n            construct: function() { [native code] }\n        },\n        toString: function() { [native code] }\n        BooleanData: false,\n        extensible: true,\n        __proto__: undefined\n    },\n    BooleanData: false\n}"

@IovoslavIovchev
Copy link
Contributor Author

@jasonwilliams As I have mentioned in the PR description, this is because of the dbg! macro. It does not render new lines or tabs, etc. but rather \n, \t, etc.

If you used println! rather than dgb! on ln 57 in src/bin/bin.rs, you would see the output beautified. Hope that helps.

@jasonwilliams
Copy link
Member

jasonwilliams commented Oct 22, 2019

@IovoslavIovchev oh my bad.
Should we change bin.rs to print!() instead of dbg!() then?

@jasonwilliams
Copy link
Member

jasonwilliams commented Oct 22, 2019

{

    BooleanData: false,
    __proto__: {
        constructor: {
            prototype: '[Cycle]'
            call: function() { [native code] },    
            construct: function() { [native code] }
        },
        valueOf: function() { [native code] },     
        toString: function() { [native code] }     
        BooleanData: false,
        extensible: true,
        __proto__: undefined
    }
}

Looks great 😁

Do we want to make it clear the difference between properties and slots?
Console.log should definitely not be printing slot data, so i suppose the use cases are different there.

@IovoslavIovchev
Copy link
Contributor Author

Well, that really depends. In my opinion we should not, as bin.rs is used for debugging purposes anyway, and it is better to see that the output is what you actually expect.

The downside obviously is that when it wraps (the way it does in your case) it gets really hard to read.

@IovoslavIovchev
Copy link
Contributor Author

Additionally, one slight mistake I made was I joined the properties and slots before printing and that resulted in

        valueOf: function() { [native code] },     
        toString: function() { [native code] }     
        BooleanData: false,

as you can see there is no comma after toString.

However, I have fixed it now. You can review the latest change.

@jasonwilliams
Copy link
Member

Sure, you also have a conflict

@IovoslavIovchev IovoslavIovchev changed the title Implement Display for Objects [WIP] Implement Display for Objects Oct 29, 2019
@jasonwilliams
Copy link
Member

No worries, was just curious

@jasonwilliams
Copy link
Member

You need any help with this?

@IovoslavIovchev
Copy link
Contributor Author

IovoslavIovchev commented Nov 13, 2019

I hit a wall with prototypes. When the execution reaches length (for instance when printing Array.prototype) I get an Err and the program panics.

// let mut engine = Executor::new(realm);
// let init = r#"
// var empty = new Array();
// var one = new Array(1);
Copy link
Contributor Author

@IovoslavIovchev IovoslavIovchev Nov 16, 2019

Choose a reason for hiding this comment

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

Currently, new Array(1) produces [1] (an array with one element, which is 1), when, in fact, it should produce an array with length 1 and an empty slot.

Copy link
Member

Choose a reason for hiding this comment

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

We will pick this up in jasonwilliams#209

@IovoslavIovchev
Copy link
Contributor Author

@jasonwilliams could you take a look again?

@IovoslavIovchev IovoslavIovchev changed the title [WIP] Implement Display for Objects Implement Display for Objects Nov 17, 2019
let callback = &args[0];
let this_arg = if args.len() > 1 {
args[1].clone()
} else {
Copy link
Member

Choose a reason for hiding this comment

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

Looks like Array.prototype.length shouldn't have a getter according to the spec

@@ -741,7 +741,9 @@ pub fn create_constructor(global: &Value) -> Value {

// Create prototype
let proto = ValueData::new_obj(Some(global));
let prop = Property::default().get(to_value(get_string_length as NativeFunctionData));
let prop = Property::default()
.get(to_value(get_string_length as NativeFunctionData))
Copy link
Member

Choose a reason for hiding this comment

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

String.prototype.length does not have a getter according to the spec https://tc39.es/ecma262/#sec-properties-of-the-string-prototype-object

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.

2 participants