forked from WordPress/wordpress-develop
-
Notifications
You must be signed in to change notification settings - Fork 0
HTML Processor perf ideas #32
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
Draft
sirreal
wants to merge
53
commits into
trunk
Choose a base branch
from
autoresearch/html-perf-2026-03-13
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
53 commits
Select commit
Hold shift + click to select a range
8d1f1fa
autoresearch prep
sirreal ba7fd5e
HTML API: Cache html_length + iterative next_visitable_token with ind…
sirreal 31e7b2e
HTML API: Remove duplicate after_tag() call and short-circuit update …
sirreal ae6c954
HTML API: Use local variables in parse_next_attribute() for hot prope…
sirreal 3f1704d
HTML API: Optimize expects_closer() with lookup table and early returns
sirreal f01b706
HTML API: Cache get_tag() result to avoid redundant substr+strtoupper
sirreal 8a5af7d
HTML API: Optimize $op construction in all step_in_* methods
sirreal fa72072
HTML API: Eliminate $op_sigil intermediate variable in remaining step…
sirreal 75b75f2
HTML API: Fast-path subdivide_text_appropriately for non-whitespace text
sirreal 14bf67e
HTML API: Replace in_array with direct comparisons in step() foreign …
sirreal 94f0b93
HTML API: Use int bookmark names to avoid string conversion per token
sirreal 5bcab7b
doc
sirreal 909cdd1
HTML API: Optimize tag name parsing with direct char check + single s…
sirreal f3c6e8d
HTML API: Read token name from current_token->node_name instead of ge…
sirreal 766aad3
HTML API: Pre-compute op string once in step() for all step_in_* methods
sirreal d256def
HTML API: Use parent::is_tag_closer() directly in step()
sirreal fd9a874
HTML API: Inline expects_closer() checks in hot-path loops
sirreal 60c019e
HTML API: Add is_pop boolean to stack events, merge pop handling
sirreal 7760015
HTML API: Inline get_token_name() for tags and text nodes in step()
sirreal 5e9529b
doc
sirreal f96b390
HTML API: Cache current_node on open elements stack
sirreal a012936
HTML API: Optimize push/pop handlers with parent::is_tag_closer()
sirreal 92802e9
HTML API: Skip change_parsing_namespace() for HTML-namespace tokens
sirreal 26a1b1c
doc
sirreal 0e5fb75
HTML API: Remove redundant isset check in provenance computation
sirreal f86c69a
HTML API: Remove unused operation property assignment from stack events
sirreal a96fcac
HTML API: Pass boolean is_pop to stack event constructor
sirreal 3a35fe3
doc
sirreal 43dcb78
HTML API: Replace provenance string with is_virtual boolean on stack …
sirreal 9fcad3b
HTML API: Skip stack operations for non-element tokens
sirreal 67eac8c
HTML API: Fast-path text nodes in step() for IN_BODY mode
sirreal 75b580b
HTML API: Inline event creation for fast-path text nodes
sirreal d9752f1
HTML API: Skip bookmark creation for fast-path text tokens
sirreal 69cc6d6
doc
sirreal 81f46c6
HTML API: Inline get_adjusted_current_node() in step()
sirreal eff38ef
HTML API: Inline is_tag_closer() check in step()
sirreal 1c9ec62
HTML API: Fast bookmark creation skipping overflow checks
sirreal 1e62032
doc
sirreal 1225e50
HTML API: Defer current_op computation past text fast path
sirreal 2930c65
HTML API: Move text fast path before tag-specific computations
sirreal ec51640
doc
sirreal c70b6cd
HTML API: Inline bookmark_token() in step()
sirreal 51c0a58
HTML API: Inline has_self_closing_flag() in step()
sirreal 3c1ba00
doc
sirreal d9af390
HTML API: Inline get_tag() in step() and compute token_name first
sirreal 8230947
doc
sirreal 3191328
HTML API: Cache is_closer result for push/pop handlers
sirreal 7392498
doc
sirreal 0788fbc
HTML API: Guard root-node check with context_node isset
sirreal 7fd30a5
doc
sirreal 6e45b4b
HTML API: Use isset() for event queue bounds checking
sirreal 78712ed
doc
sirreal 47b88e2
HTML API: Reduce push handler namespace checks for HTML elements
sirreal File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| #!/bin/bash | ||
| set -euo pipefail | ||
|
|
||
| # Run HTML API tests — suppress success output, only show errors | ||
| ./vendor/bin/phpunit -c tests/phpunit/tests/html-api/phpunit.xml --stop-on-error --stop-on-failure --stop-on-warning --stop-on-defect 2>&1 | tail -5 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| # Autoresearch: HTML Tag Processor Performance | ||
|
|
||
| ## Objective | ||
|
|
||
| Optimize `WP_HTML_Processor::next_token()` tokenization throughput on html-standard.html (~large real-world HTML). The benchmark iterates all tokens with no modifications — purely read-only tokenization speed. | ||
|
|
||
| ## Metrics | ||
|
|
||
| - **Primary**: mean execution time (ms, lower is better) via `hyperfine` | ||
| - **Secondary**: peak memory (bytes, lower is better) via `/usr/bin/time -l` | ||
|
|
||
| ## How to Run | ||
|
|
||
| `./autoresearch.sh` — runs hyperfine, outputs `METRIC mean_ms=number` lines. | ||
|
|
||
| ## Files in Scope | ||
|
|
||
| - `src/wp-includes/html-api/class-wp-html-processor.php` — HTML parser | ||
| - `src/wp-includes/html-api/class-wp-html-tag-processor.php` — HTML syntax parser | ||
| - `src/wp-includes/html-api/class-wp-html-attribute-token.php` — attribute token object (6 props, allocated per attr) | ||
| - `src/wp-includes/html-api/class-wp-html-span.php` — span object (2 props, allocated on dup attrs) | ||
|
|
||
| ## Off Limits | ||
|
|
||
| - Test files | ||
| - `bench.php` and `bootstrap-html-api.php` | ||
| - Any file outside `src/wp-includes/html-api/` | ||
|
|
||
| ## Constraints | ||
|
|
||
| - PHPUnit tests must pass: `./vendor/bin/phpunit -c tests/phpunit/tests/html-api/phpunit.xml --stop-on-error --stop-on-failure --stop-on-warning --stop-on-defect` | ||
| - No new dependencies | ||
| - stddev and outliers from hyperfine must remain acceptable | ||
| - Changes must preserve all existing behavior | ||
|
|
||
| ## What's Been Tried | ||
|
|
||
| ### Baseline: 2453ms mean (stddev 40ms) | ||
|
|
||
| ### Wins (cumulative, all committed) | ||
|
|
||
| 1. **Cache `strlen($this->html)` in `$this->html_length`** — Replaced all `strlen($this->html)` calls in hot paths with cached property. Negligible on its own (strlen is O(1) in PHP), but eliminates function call overhead. | ||
|
|
||
| 2. **Convert recursive `next_visitable_token()` to iterative loop + index pointer** — Replaced `array_shift()` with index-based access, replaced recursive calls with `continue`. 2453→2386 (~2.7%) | ||
|
|
||
| 3. **Remove duplicate `after_tag()` call** — `parse_next_tag()` called `after_tag()` but was only called from `base_class_next_token()` which already calls it. Removed redundant call. Also guarded update-flushing logic with emptiness checks. 2386→2282 (~4.4%) | ||
|
|
||
| 4. **Use local variables in `parse_next_attribute()`** — Cached `$this->html` and `$this->bytes_already_parsed` in local vars, inlined `skip_whitespace()`. Marginal. | ||
|
|
||
| 5. **Optimize `expects_closer()` with lookup table** — Replaced `in_array()` + `is_void()` with `isset()` on a const array. Added early returns for `#text`, `#comment`. 2282→2204 (~3.4%) | ||
|
|
||
| 6. **Cache `get_tag()` result** — Avoid redundant `substr + strtoupper` when `get_tag()` is called multiple times per token (from `step()`, `step_in_body()`, `get_token_name()`). 2204→2132 (~3.3%) | ||
|
|
||
| 7. **Optimize `$op` construction in all step_in_* methods** — Replace `get_token_type()` + conditional sigil with direct `parser_state` check. Eliminates method call and string interpolation. 2132→2108 (~1.1%) | ||
|
|
||
| 8. **Fast-path `subdivide_text_appropriately()`** — Skip null/whitespace detection when text starts with a regular character. Marginal. | ||
|
|
||
| 9. **Replace `in_array` with direct comparisons in `step()` foreign content check** — Avoid temporary array allocation. Also converted `bookmark_token()` to return null on failure instead of throwing. | ||
|
|
||
| 10. **Use int bookmark names** — Avoid int-to-string conversion per token by passing counter directly. ~14ms. | ||
|
|
||
| ### Current: 1323ms mean (stddev 24ms) — 46.1% improvement | ||
|
|
||
| 11. **Optimize tag name parsing with direct char check + single strcspn** — Replace `strspn()` + `strcspn()` combo for tag name detection with direct character range comparison. Move bounds check before character access. ~50ms. | ||
|
|
||
| 12. **Read token name from current_token->node_name** — In all step_in_* methods, read `$this->state->current_token->node_name` instead of calling `get_token_name()`. Avoids method call + switch per token. ~30ms. | ||
|
|
||
| 13. **Pre-compute $op string once in step()** — The operation string (`+DIV`, `-DIV`, `#text`) was recomputed in every step_in_* method. Compute once in step() and store as property. Marginal but removes 55 lines of redundant code. | ||
|
|
||
| 14. **Use parent::is_tag_closer() directly in step()** — During step(), current_element is always null so the overridden is_tag_closer() virtual check always falls through. Skip the dispatch. Marginal. | ||
|
|
||
| 15. **Inline expects_closer() checks in hot-path loops** — Replace method calls with inline property checks and isset() lookup in both next_visitable_token() and step(). ~50ms. | ||
|
|
||
| 16. **Add is_pop boolean to stack events, merge pop handling** — Pre-computed boolean on WP_HTML_Stack_Event replaces string comparison per event. Merged two separate is_pop blocks into one. ~10ms. | ||
|
|
||
| 17. **Inline get_token_name() for tags and text in step()** — Fast-path matched tags (call get_tag() directly) and text nodes (return '#text' immediately), avoiding method call + switch dispatch. ~40ms. | ||
|
|
||
| 18. **Cache current_node on open elements stack** — Maintain a cached reference updated on push/pop/remove_node. Avoids calling `end()` on every `current_node()` access. ~40ms. | ||
|
|
||
| 19. **Optimize push/pop handlers with parent::is_tag_closer()** — Use `parent::is_tag_closer()` instead of `$this->is_tag_closer()` to skip is_virtual() dispatch chain. Cache current_token in local variable. ~50ms. | ||
|
|
||
| 20. **Skip change_parsing_namespace() for HTML-namespace tokens** — Avoid calling the method when the namespace is already 'html'. Marginal. | ||
|
|
||
| 21. **Remove redundant isset in provenance computation** — When is_virtual is false, current_token is guaranteed set. Marginal. | ||
|
|
||
| 22. **Remove unused operation property assignment** — The string operation property is dead code since all checks use is_pop boolean. Marginal. | ||
|
|
||
| 23. **Pass boolean is_pop directly to stack event constructor** — Replace string comparison `self::POP === $operation` with a direct boolean parameter. ~30ms. | ||
|
|
||
| 24. **Skip stack operations for non-element tokens** — Non-element tokens (text, comments) are always immediately popped from the stack on the next step(). Skip the actual stack push/pop and create the event directly. Also skip adding them to breadcrumbs (they cancel out). ~110ms. | ||
|
|
||
| 25. **Fast-path text nodes in step() for IN_BODY mode** — Inline the text node handling from step_in_body() directly in step(). Avoids method call, variable assignments, and switch dispatch. ~40ms. | ||
|
|
||
| 26. **Inline event creation for fast-path text nodes** — Create the stack event directly in the fast path instead of going through insert_html_element(). ~20ms. | ||
|
|
||
| 27. **Skip bookmark creation for fast-path text tokens** — Text tokens don't need bookmarks for read-only tokenization. Skip bookmark_token(), set_bookmark(), and WP_HTML_Span allocation. Create lightweight WP_HTML_Token with no bookmark. ~65ms. | ||
|
|
||
| 28. **Inline get_adjusted_current_node() in step()** — Replace method call with inline logic. For full parsers, just calls current_node(). ~20ms. | ||
|
|
||
| 29. **Inline is_tag_closer() in step()** — Make is_closing_tag protected and inline the check. For start tags, short-circuits on is_closing_tag=false. ~12ms. | ||
|
|
||
| 30. **Fast bookmark creation** — Skip state checks, array_key_exists, and count() overflow guard in set_bookmark. Since bookmarks use monotonically increasing integer names, overflow can't happen. ~14ms. | ||
|
|
||
| 31. **Defer current_op past text fast path** — Skip op string computation for fast-pathed text tokens. Marginal. | ||
|
|
||
| 32. **Move text fast path before tag-specific computations** — Place text node fast path right after token parsing, inside the subdivide_text_appropriately block. Skips adjusted_current_node, is_matched_tag, is_closer, is_start_tag, and token_name ternary chain for text tokens. ~24ms. | ||
|
|
||
| 33. **Inline bookmark_token() in step()** — Replace method call with inline code. Marginal. | ||
|
|
||
| 34. **Inline has_self_closing_flag() in step()** — Make token_starts_at and token_length protected. For non-matched tags, short-circuits. For matched tags, avoids method call. ~35ms. | ||
|
|
||
| 35. **Inline get_tag() in step()** — Make tag_name_starts_at, tag_name_length, tag_name_cache protected. Inline the strtoupper(substr()) computation, compute token_name first, use cached value for BR check. ~25ms. | ||
|
|
||
| 36. **Cache is_closer result for push/pop handlers** — Store is_closer from step() in property, read in push/pop handlers instead of calling parent::is_tag_closer() per push and pop. ~30ms. | ||
|
|
||
| 37. **Guard root-node check with context_node isset** — Root-node bookmark only exists in fragment parsers. Guard string comparison so full parsers avoid it. ~14ms. | ||
|
|
||
| 38. **Use isset() for event queue bounds checking** — Replace count() comparison with isset(). Marginal. | ||
|
|
||
| ### Dead Ends | ||
|
|
||
| - **Inline `skip_whitespace()`** — No improvement; PHP optimizes short function calls well. | ||
| - **`call_user_func` → direct closure invocation** — No improvement in PHP 8.5. | ||
| - **Fast-path no-attribute tags** — Added branch overhead without enough benefit. | ||
| - **Replace `is_callable` with `null !==` in WP_HTML_Token destructor** — Made things slightly worse. | ||
| - **Remove redundant `$this->namespace = 'html'` in WP_HTML_Token constructor** — Made things slightly worse (combined with destructor change). | ||
| - **Defer `$this->attributes = array()` from after_tag() to ensure_attributes_parsed()** — Empty arrays are cheap in PHP 8 (shared empty array via COW). No improvement. | ||
| - **Replace WP_HTML_Span bookmarks with packed integers** — External code (interactivity API, block-template.php) accesses `$bookmark->start` and `$bookmark->length` directly. Can't change format. | ||
| - **Replace `count() > 0` with truthiness check in after_tag()** — `count()` on PHP arrays is O(1), negligible overhead. | ||
| - **Reorder `$parse_in_current_insertion_mode` to check namespace first** — Within noise. | ||
| - **Optimize text-tag boundary strspn check** — Fires less frequently than tag parsing; within noise. | ||
|
|
||
| ### Architecture Notes | ||
|
|
||
| - ~1,077,000 tokens in html-standard.html (~1.8μs/token) | ||
| - Each token creates: WP_HTML_Token + WP_HTML_Span (bookmark) + 1-2 WP_HTML_Stack_Event + N WP_HTML_Attribute_Token | ||
| - Object allocations are a significant remaining bottleneck but deeply embedded in the architecture | ||
| - `strpos`/`strspn`/`strcspn` are C-implemented and already fast; the overhead is in PHP-level logic around them | ||
| - The insertion mode dispatch (big switch in step()) is a fixed cost that's hard to reduce | ||
| - External code depends on WP_HTML_Span bookmark format — can't pack bookmarks into integers | ||
| - WP_HTML_Token destructor changes (is_callable → null !==, call_user_func → direct invocation) surprisingly hurt performance | ||
|
|
||
| ### Unexplored Ideas | ||
|
|
||
| - **Object pooling for WP_HTML_Stack_Event** — reuse event objects instead of allocating new ones | ||
| - **Combined token+event object** — merge WP_HTML_Token and WP_HTML_Stack_Event to reduce allocations | ||
| - **Pre-scanned tag name table** — for known HTML elements, use a lookup instead of substr+strtoupper | ||
| - **Avoid WP_HTML_Token allocation for reprocessed tokens** — skip constructor when reprocessing same token | ||
| - **Eliminate WP_HTML_Stack_Event allocation** — use parallel arrays instead of objects for event queue | ||
| - **Replace WP_HTML_Stack_Event with struct-of-arrays** — Use 3 parallel arrays (eq_tokens, eq_is_pop, eq_is_virtual) instead of WP_HTML_Stack_Event objects. No measurable improvement; PHP allocates small objects efficiently | ||
| - **Fast-path comments in step()** — No comments in html-standard.html; adds branch overhead with no benefit | ||
| - **Skip has_self_closing_flag() for HTML namespace** — Added namespace check costs same as the method call; no improvement | ||
| - **Cache stack_of_open_elements reference** — PHP property chains already well-optimized; no improvement | ||
| - **Cache op strings with ??=** — Hash table lookup costs more than short string concatenation | ||
| - **Defer current_op past text fast path** — Text tokens don't concatenate (not matched tags); saving is just one pointer assignment | ||
| - **Skip stack for void HTML elements** — Extra checks per element (isset on const array) cost more than savings from few void elements in benchmark | ||
| - **Skip bookmark creation for comment tokens** — same approach as text tokens | ||
| - **Fast-path comments in step()** — similar to text fast-path; comments in IN_BODY are always simple insert+return | ||
| - **Cache stack_of_open_elements reference** — avoid repeated property access chain | ||
| - **Avoid WP_HTML_Token allocation for text tokens** — reuse a single text token object |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,23 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| #!/bin/bash | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Quick syntax check before benchmarking | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| php -l src/wp-includes/html-api/class-wp-html-tag-processor.php > /dev/null 2>&1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| php -l src/wp-includes/html-api/class-wp-html-processor.php > /dev/null 2>&1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| php -l src/wp-includes/html-api/class-wp-html-attribute-token.php > /dev/null 2>&1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| TMPFILE=$(mktemp) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| trap "rm -f $TMPFILE" EXIT | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Run benchmark | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| hyperfine --warmup 2 --min-runs 10 --export-json "$TMPFILE" './bench.php' > /dev/null | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Extract metrics | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| php -r ' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| $data = json_decode(file_get_contents($argv[1]), true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| $r = $data["results"][0]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| printf("METRIC mean_ms=%.1f\n", $r["mean"] * 1000); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| printf("METRIC stddev_ms=%.1f\n", $r["stddev"] * 1000); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| printf("METRIC min_ms=%.1f\n", $r["min"] * 1000); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| printf("METRIC max_ms=%.1f\n", $r["max"] * 1000); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+17
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The inline PHP script for extracting metrics is not very robust. If
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ' "$TMPFILE" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| #!/usr/bin/env php | ||
| <?php | ||
| require_once __DIR__ . '/bootstrap-html-api.php'; | ||
| $html = file_get_contents( dirname( __DIR__ ) . '/bench-html-api/tests/benchmarks/data/html-standard.html' ); | ||
| $p = WP_HTML_Processor::create_full_parser( $html ); | ||
| while ( $p->next_token() ) { | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| <?php | ||
|
|
||
| require_once __DIR__ . '/src/wp-includes/compat.php'; | ||
| require_once __DIR__ . '/src/wp-includes/utf8.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-doctype-info.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-attribute-token.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-span.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-text-replacement.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-tag-processor.php'; | ||
|
|
||
| // HTML Processor | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-stack-event.php'; | ||
| require_once __DIR__ . '/src/wp-includes/class-wp-token-map.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/html5-named-character-references.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-decoder.php'; | ||
|
|
||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-unsupported-exception.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-active-formatting-elements.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-open-elements.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-token.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-processor-state.php'; | ||
| require_once __DIR__ . '/src/wp-includes/html-api/class-wp-html-processor.php'; | ||
|
|
||
| if ( ! function_exists( 'esc_attr' ) ) { | ||
| function esc_attr( $s ) { | ||
| return str_replace( array( '<', '>', '"' ), array( '<', '>', '"' ), $s ); | ||
| } | ||
| } | ||
|
|
||
| if ( ! function_exists( '__' ) ) { | ||
| function __( $s ) { | ||
| return $s; | ||
| } | ||
| } | ||
|
|
||
| if ( ! function_exists( '_doing_it_wrong' ) ) { | ||
| function _doing_it_wrong( $message ) { | ||
| trigger_error( $message ); | ||
| } | ||
| } | ||
|
|
||
| if ( ! function_exists( 'wp_kses_uri_attributes' ) ) { | ||
| function wp_kses_uri_attributes() { | ||
| return array(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
The use of
| tail -5is a bit fragile as it might hide important error details if the output fromphpunitis longer than 5 lines. A more robust approach would be to capture the full output and display it only when the command fails. This ensures you see all relevant error information when tests fail, without cluttering the output on success.