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

LibJS+WebContent: Implement console.table #1027

Conversation

GasimGasimzada
Copy link
Contributor

@GasimGasimzada GasimGasimzada commented Aug 10, 2024

Description

Implement console.table similar to how it is handled in other browsers. In this case, the Console creates a data structure and passed that structure to the Printer. In the printer side, unlike in other browsers, I decided to allow expanding arrays and objects in the table instead of just saying that the element is an array or object:

image

Algorithm

Below is the detailed explanation of the algorithm:

There are two parts to this algorithm -- First one is about choosing the column that represents indices and the second one is assigning properties to columns.

Setting the index column:

The index column's name is represented as "(index)" (parentheses are part of the column name).

  • If the first argument (let's call it tabularData) is a array, we iterate over the array and assign it to "(index)" column.
Example:
console.table(["a", "b", "c"]);

outputs

(index) Value
0 "a"
1 "b"
2 "c
  • If the first argument is an object, we iterate over all the enumerable keys and assign the key to the "(index)" column.

    Example:
    console.table({ a: "10", b: 20, c: 30 });

    outputs

    (index) Value
    a 10
    b 20
    c 30

Assigning properties to columns:

As we iterate over each item of the object/array, we check the type of each item (array element or object property):

  • If the item is an array, iterate over the array, create a column that's named as the array element index and assign the value at the index to the column value.

    Example:
    console.table([
      ["hello", "world"]
      ["a", "b", "c"]
    ]);

    outputs

    (index) 0 1 2
    0 "hello" "world"
    1 "a" "b" "c"
  • If the item is an object, enumerate over the object propreties, create a column that's named as the property key and assign the value at the key to the the property value.

    Example:
    console.table([
      {firstName: "hello", lastName: "world"}
      {a: 10, b: 20, c: 30]
    ]);

    outputs

    (index) firstName lastName a b c
    0 "hello" "world"
    1 10 20 30
  • If item is neither array, nor object, assign the object to column named "Value".

    Example:
    console.table([10, 20, 30]);

    outputs

    (index) Value
    0 10
    1 20
    2 30
  • When the second argument (let's call it properties) is passed, we show "(index)", "Value", the the columns defined in properties.

    Example:
    console.table([
      {firstName: "hello", lastName: "world"}
      {a: 10, b: 20, c: 30],
      "hello"
    ], ["firstName", "lastName"]);

    outputs

    (index) firstName b Value
    0 "hello"
    1 20
    2 "hello"

Considerations:

  • The creation of columns based on the item type is only done one level. If there is an array or object after first level, we just print it without creating new columns.

    Example:
    console.table([
      [{ a: 10 }, { b:  20 }]
      { c: [10, 20], d: [30, 40] }
    ])

    Outputs:

    (index) 0 1 c d
    0 { a: 10 } { b: 20 }
    1 [10, 20] [30, 40]
  • The order of elements can affect the order the columns, including the "Value" column, because columns are populated as we iterate over rows.

    Example:
    console.table([
      {firstName: "hello", lastName: "world"}
      {a: 10, b: 20, c: 30],
      "test"
    ]);

    outputs

    (index) firstName lastName a b c Value
    0 "hello" "world"
    1 10 20 30
    2 "hello" "world" test

    while

    console.table([
      {a: 10, b: 20, c: 30]
      "test",
      {firstName: "hello", lastName: "world"}
    ]);

    outputs

    (index) a b c Value firstName lastName
    0 10 20 30
    1 test
    2 "hello" "world"
  • "(index)" is always the first column

  • "(index)" and "Value" columns are NOT affected by the properties argument

Spec Steps

Spec PR: whatwg/console#237 (still in progress)

Changes

  • Expose table from console object
  • Add new Table log level
  • Create a JS object that represents table rows and columns
  • Print table as HTML using WebContentConsoleClient

@GasimGasimzada GasimGasimzada force-pushed the js-lib-web-content-console-table branch 6 times, most recently from 783ef6c to 986a904 Compare August 11, 2024 11:06
@GasimGasimzada GasimGasimzada marked this pull request as ready for review August 11, 2024 11:37
@GasimGasimzada GasimGasimzada force-pushed the js-lib-web-content-console-table branch 3 times, most recently from b74a281 to d1dc9b3 Compare August 11, 2024 12:01
@GasimGasimzada GasimGasimzada changed the title JSLib, WebContent: Implement console.table LibJS, WebContent: Implement console.table Aug 11, 2024
@circl-lastname
Copy link
Contributor

circl-lastname commented Aug 11, 2024

Commit should be titled LibJS+WebContent

@GasimGasimzada GasimGasimzada force-pushed the js-lib-web-content-console-table branch from d1dc9b3 to 1ef95a8 Compare August 12, 2024 13:37
Copy link
Member

@AtkinsSJ AtkinsSJ left a comment

Choose a reason for hiding this comment

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

Thanks for doing this! A couple of general comments besides the CSS ones:

I saw you made a PR to the console spec, that's great! Can you please include the spec steps you added as comments in this code? Put a note that links to the PR and says it's not yet in the actual spec. That'll make it easier to follow what's going on. (And help to verify that your algorithm works as intended.)

Also, the way the properties parameter works doesn't match what I see in Firefox or Chrome:
image
(Ladybird on left, Firefox on right. Chrome output was the same as Firefox.)

Base/res/ladybird/inspector.css Outdated Show resolved Hide resolved
Base/res/ladybird/inspector.css Outdated Show resolved Hide resolved
@GasimGasimzada
Copy link
Contributor Author

GasimGasimzada commented Aug 13, 2024

I saw you made a PR to the console spec, that's great! Can you please include the spec steps you added as comments in this code? Put a note that links to the PR and says it's not yet in the actual spec. That'll make it easier to follow what's going on. (And help to verify that your algorithm works as intended.)

I added a link to the PR for the spec.

Thanks for doing this! A couple of general comments besides the CSS ones:

I saw you made a PR to the console spec, that's great! Can you please include the spec steps you added as comments in this code? Put a note that links to the PR and says it's not yet in the actual spec. That'll make it easier to follow what's going on. (And help to verify that your algorithm works as intended.)

Also, the way the properties parameter works doesn't match what I see in Firefox or Chrome: image (Ladybird on left, Firefox on right. Chrome output was the same as Firefox.)

Thank you for noticing this. Let me see if I can figure out what's going on here.

@GasimGasimzada GasimGasimzada changed the title LibJS, WebContent: Implement console.table LibJS+WebContent: Implement console.table Aug 13, 2024
@ladybird-bot
Copy link
Collaborator

Hello!

One or more of the commit messages in this PR do not match the Ladybird code submission policy, please check the lint_commits CI job for more details on which commits were flagged and why.
Please do not close this PR and open another, instead modify your commit message(s) with git commit --amend and force push those changes to update this PR.

@GasimGasimzada GasimGasimzada force-pushed the js-lib-web-content-console-table branch 3 times, most recently from 75ef864 to 47b8da7 Compare August 13, 2024 17:23
@GasimGasimzada
Copy link
Contributor Author

GasimGasimzada commented Aug 13, 2024

@AtkinsSJ You are passing two different values between browsers:

On the left screenshot, the first argument is an object while on the right screenshot, the first argument is an array that contains an object (highlighted them with orange marker):

357458864-567d7002-d164-4e33-8e06-b86f1e84bba41

@AtkinsSJ
Copy link
Member

Ah whoops! I'm glad it's me and not your code. 😆

@AtkinsSJ
Copy link
Member

OK, I think I wasn't clear with what I meant.

If you look at the other console methods, our code has the steps from the spec quoted exactly, then the code that implements them. For example, our Console::count() code looks like:

    // 1. Let map be the associated count map.
    auto& map = m_counters;

    // 2. If map[label] exists, set map[label] to map[label] + 1.
    if (auto found = map.find(label); found != map.end()) {
        map.set(label, found->value + 1);
    }
    // 3. Otherwise, set map[label] to 1.
    else {
        map.set(label, 1);
    }

	// ...

We like doing this for a few reasons: It makes it clear that the code matches the spec; it's easier to spot errors; and if the spec changes in the future, it's easier to see what needs changing. (I think someone was working on an automated way to check this, at some point...) As an added bonus it helps us spot any problems in the spec itself.

If you could do the same with your draft spec's steps, with a note at the top to say it's based on changes that aren't in the official spec yet, that would be good.

Also, your commit title still says "JSLib" when it should say "LibJS". 😅

@GasimGasimzada
Copy link
Contributor Author

GasimGasimzada commented Aug 15, 2024

If you could do the same with your draft spec's steps, with a note at the top to say it's based on changes that aren't in the official spec yet, that would be good.

Makes sense. I'll add the steps in the code 😊

Also, your commit title still says "JSLib" when it should say "LibJS". 😅

I'll fix that too. I thought this was about the PR title, not commit message title :D

@GasimGasimzada GasimGasimzada force-pushed the js-lib-web-content-console-table branch 4 times, most recently from 8e921a1 to 7662c94 Compare August 15, 2024 16:16
@GasimGasimzada
Copy link
Contributor Author

@AtkinsSJ I fixed the commit message and also added steps of the algorithm, and also added "WIP" next to the table function's comment. Let me know what you think.

Copy link
Member

@AtkinsSJ AtkinsSJ left a comment

Choose a reason for hiding this comment

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

Thank you, it's a lot easier to examine the code when it's right next to the spec algorithm. (Even if it's a WIP algorithm.)

Someone else who's more familiar with LibJS will need to give this a look too, but overall this looks fine, just a few small things.

Userland/Libraries/LibJS/Console.cpp Show resolved Hide resolved
Userland/Libraries/LibJS/Console.cpp Outdated Show resolved Hide resolved
Userland/Libraries/LibJS/Console.cpp Outdated Show resolved Hide resolved
Userland/Libraries/LibJS/Console.cpp Outdated Show resolved Hide resolved
@GasimGasimzada GasimGasimzada force-pushed the js-lib-web-content-console-table branch from 7662c94 to 42b4f48 Compare August 20, 2024 22:38
- Expose table from console object
- Add new Table log level
- Create a JS object that represents table rows and columns
- Print table as HTML using WebContentConsoleClient
@GasimGasimzada GasimGasimzada force-pushed the js-lib-web-content-console-table branch from 42b4f48 to fe399ee Compare August 20, 2024 22:54
Copy link
Member

@AtkinsSJ AtkinsSJ left a comment

Choose a reason for hiding this comment

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

Great! I'm happy to merge this now, and if we do find any issues we can fix them later. Hopefully this will help demonstrate that the algorithm you wrote is correct, too. :^)

Oh, and in future, whenever you've pushed changes that resolve a review comment, click the [Resolve conversation] button. That makes it clear to maintainers that it's ready for another review or merge.

@AtkinsSJ AtkinsSJ merged commit 785180d into LadybirdBrowser:master Aug 22, 2024
5 of 6 checks passed
@GasimGasimzada GasimGasimzada deleted the js-lib-web-content-console-table branch August 26, 2024 18:59
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.

4 participants