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

Interactivity API: Support .length on numeric arrays and strings on the server #7751

Closed

Conversation

sirreal
Copy link
Member

@sirreal sirreal commented Nov 8, 2024

Add .length to directives processing on the server on strings and numeric arrays.

The Interactivity API does not support the .length property on numeric arrays or strings on the server. This is one place where the behavior of server rendering is markedly different from client side rendering. The Interactivity API tries to align client and server rendering so that the behavior is the same.

String and array have a .length property in JavaScript that the directives processor can provide in order to support directives like the following:

<div data-wp-interactive="example">
  <div data-wp-bind--hidden="!state.list.length">
    <input type="range" min="1" data-wp-bind--max="state.list.length">
  </div>
  <div data-wp-bind--hidden="!state.string.length">
    <h1 data-wp-text="state.string"></h1>
  </div>
</div>

Testing for falsy .length is a common JavaScript idiom.

Trac ticket: https://core.trac.wordpress.org/ticket/62582


Known issues

Differences in string encodings may result in different results for the .length of a string between what the server reports and what JavaScript would detect.

For example:

$s = "foo";
var_dump(
    $s,
    strlen( $s ),
    mb_strlen( mb_convert_encoding( $s, 'UTF-16', mb_internal_encoding() ), 'UTF-16' ),
);
// string(3) "foo"
// int(3)
// int(3)

$s = "é";
var_dump(
    $s,
    strlen( $s ),
    mb_strlen( mb_convert_encoding( $s, 'UTF-16', mb_internal_encoding() ), 'UTF-16' ),
);
// string(2) "é"
// int(2)
// int(1)

While in JavaScript:

var s = 'foo';
console.log( "%o", s.length );
// 3
s = 'é'
console.log( "%o", s.length );
// 1

The proposed implementation for string length checking currently relies on strlen. This should be correct for any single-byte strings, but will often be incorrect with multibyte strings.

JavaScript strings are UTF-16 encoded. This can be calculated in PHP, but doing so relies on knowing the input string encoding and relying on encoding conversions that may be costly, like mb_strlen( mb_convert_encoding( $s, 'UTF-16', mb_internal_encoding() ) in the example above.

This seems sufficient at the moment, if the precise length of a string must be known on the server then derived state or a static state property can be used with the appropriate conversion. What I suspect is the most common use case for string length checking (whether the string is empty or not) will always work correctly. Including information about this caveat in a dev note and documentation with workarounds will help.


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

Copy link

github-actions bot commented Nov 8, 2024

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@luisherranz
Copy link
Member

I'm up for this 🙂

Do you want me to add it to the WP 6.8 iteration?

@sirreal
Copy link
Member Author

sirreal commented Nov 21, 2024

Do you want me to add it to the WP 6.8 iteration?

Yeah, I think so! I was worried this would create a precedent where many things would need to be added, but it doesn't seem like there are actually many cases that are similar to this, really just .length on strings and arrays.

Relevant conversation on Core Slack.

@sirreal sirreal changed the title Interactivity API: Support .length access on numeric arrays on the server Interactivity API: Support .length on numeric arrays and strings on the server Nov 21, 2024
@sirreal sirreal force-pushed the iapi/add-magic-array-length-property branch from 86727eb to 85581e4 Compare November 27, 2024 10:22
@sirreal sirreal marked this pull request as ready for review November 27, 2024 10:40
Copy link

github-actions bot commented Nov 27, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props jonsurrell, gziolo, luisherranz.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@sirreal
Copy link
Member Author

sirreal commented Nov 27, 2024

This is ready for review @luisherranz @michalczaplinski @DAreRodz @cbravobernal.

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

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

Code looks good, nice unification 👍🏻

@gziolo
Copy link
Member

gziolo commented Dec 2, 2024

Committed with https://core.trac.wordpress.org/changeset/59477.

@gziolo gziolo closed this Dec 2, 2024
@sirreal sirreal deleted the iapi/add-magic-array-length-property branch December 12, 2024 10:35
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.

3 participants