aboutsummaryrefslogtreecommitdiffstats
path: root/tests
Commit message (Collapse)AuthorAgeFilesLines
* Merge "Make stats from RevisionOutputCache consistent with those from ↵HEADmasterjenkins-bot14 days1-0/+8
|\ | | | | | | ParserCache"
| * Make stats from RevisionOutputCache consistent with those from ParserCacheC. Scott Ananian2025-04-041-0/+8
| | | | | | | | | | | | In particular, add content model and render reason statistics. Change-Id: I5286425794cc7827705bfc0e7f004543e383443c
* | Merge "Improve PHPUnit parallel split_group generation algorithm"jenkins-bot14 days3-4/+9453
|\ \
| * | Improve PHPUnit parallel split_group generation algorithmArthur Taylor14 days3-4/+9453
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Given the constraints that the PHPUnit test classes need to be run in their original order, that we might have incomplete information about the test duration, and that the test durations vary significantly (from 0 seconds to many tens of seconds), we want to make best efforts to create split_groups with similar durations (and in so doing, minimise the duration of the split_group with the longest runtime). The existing algorithm takes the number of tests and the total duration of tests and tries to create an even split by either duration or test count (assuming that the zero-duration tests actually take a similar, non-zero time to execute). This algorithm can potentially place two long-running tests into the same group - the group might be close to its duration limit, and the next test may be a long-running test. In such a case, the group can end up significantly bigger than desired. Change the group-splitting algorithm to chunk the tests into up to 200 chunks, and assign the chunks to split_groups using a dynamic programming algorithm that uses backtracking to find an optimal allocation of chunks to split_groups. Bug: T389189 Change-Id: I61ae44f3fca4a890947ea1499a99690a4fcc2bb8
* | | Merge "ManualLogEntry: Check RecentChanges bot flag before POSTSEND"jenkins-bot14 days1-0/+101
|\ \ \ | |/ / |/| |
| * | ManualLogEntry: Check RecentChanges bot flag before POSTSENDDreamy Jazz2025-04-031-0/+101
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Why: * ManualLogEntry::publish causes an entry to be added to the recentchanges table as well as other publishing actions for the log entry. * This is done in a DeferredUpdate to avoid writes that block the response to the user unnecessarily. * However, doing this means that if we assign a temporary user right during the course of the POST request (such as in the case of an extension wanting to make lots of log entries) this is not seen in the RecentChanges object created at the POSTSEND stage. * Creating the RecentChanges entry at the time of calling ::publish allows temporary user rights, such as 'bot', to take effect and mark the log entries as bot actions. ** We still put the writes to the DB POSTSEND as we only need to create the RecentChanges object to get the bot flag set correctly. What: * Update ManualLogEntry::publish to create the RecentChanges object outside the POSTSEND DeferredUpdate. * Add tests for ManualLogEntry which was previously completely untested (though likely indirectly tested through code which uses this class). ** Adding the tests allows verification that the change performed actually does what we want it to do. Bug: T387659 Change-Id: I80d906bbc1cad180a815477477d9081f9775a197
* | | Merge "DateFormatter: Fix exception if user date option is not available"jenkins-bot2025-04-071-14/+48
|\ \ \
| * | | DateFormatter: Fix exception if user date option is not availableTim Starling2025-04-071-14/+48
| | |/ | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | If the user's date option is not available in the selected user language, fall back to the site default and then to "dmy", the last being guaranteed to exist since all languages are merged with MessagesEn.php. Add test. Change-Id: I9ccc6ebe747070fec2b80398a8251924c9a28fbc
* | | block: Fix DBS::acquireTarget() race using GET_LOCK()Tim Starling2025-04-071-0/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A crude solution for the acquireTarget() race condition. Use SQL GET_LOCK() to lock the target from the acquireTarget() call until the transaction is committed. Add FOR UPDATE to the acquireTarget() SELECT, otherwise it just sees the snapshot version of the row and inserts a new row anyway. Add a test which reliably failed prior to the change. Reword the ipb-block-not-found message. This is normal for simultaneous blocks of the same target. Don't contact us. In the API, remap it to "alreadyblocked". Bug: T389028 Change-Id: I1fa35bf08d456a93930194786f77df389217ba61
* | | Merge "editpage: Refactor user right, rate limit and block checks to use ↵jenkins-bot2025-04-067-299/+148
|\ \ \ | | | | | | | | | | | | Authority"
| * | | editpage: Refactor user right, rate limit and block checks to use AuthorityBartosz Dziewoński2025-04-057-299/+148
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Replace EditRightConstraint, UserBlockConstraint, and most of UserRateLimitConstraint with the new AuthorizationConstraint. Instead of many separate checks, everything is now handled by one authorizeWrite() call. Move 'editcontentmodel' rate limit to ContentModelChangeConstraint (by making it use authorizeWrite()). Keep 'linkpurge' rate limit in a separate check, renamed from UserRateLimitConstraint to LinkPurgeRateLimitConstraint, since the way it works in unusual and not portable to Authority without more refactoring in EditPage. AuthorizationConstraint needs some special handling to produce the idiosyncratic result codes required by EditPage, but luckily PermissionStatus gives us everything we need for that. Bug: T271975 Bug: T386346 Change-Id: Ic9f6f2fbd29efa3e349517013da540a363c263b5
* | | | Merge "Hard deprecate OutputPage::setRevisionTimestamp()"jenkins-bot2025-04-061-0/+1
|\ \ \ \ | |/ / / |/| | |
| * | | Hard deprecate OutputPage::setRevisionTimestamp()C. Scott Ananian2025-04-041-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This method was already deprecated, and mentioned in the RELEASE-NOTES. This patch just removes use of the method in core; it does not seem to be used outside core: https://codesearch.wmcloud.org/deployed/?q=-%3EsetRevisionTimestamp%5C%28 Bug: T301020 Follows-Up: Iee09b1591bfa11142686c9043a8294e7e77d2b61 Change-Id: I7528b9bc3522ed05f41f0915e38940b4a1fd48ce
* | | | REST: Remove unused setUseParserCache() as potential footgunTimo Tijhof2025-04-051-47/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Added in 2022 with I7d97c9e2d4 (c6a0d433ec) for Ie430acd075 (e82f11c246) which was (after a revert and re-apply) eventually removed after the warmup completed (I852060c8a4, 3df4952385). Bug: T322672 Bug: T387478 Change-Id: I1921b4f985fb27b2227aef4a0eba6751c1c0b8d5
* | | | Sync up core repo with ParsoidC. Scott Ananian2025-04-045-19/+196
| |/ / |/| | | | | | | | | | | | | | This now aligns with Parsoid commit 0965c908f046d659aab16b4023cc8de9ded1fce7 Change-Id: Ic007c7b4a893329de8499a88bb0edcb4b04d0905
* | | storage: Assert CategoryMembershipChangeJob via traitMáté Szabó2025-04-0411-34/+108
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Why: - As suggested on I14944639e00407f59380c8787fd2810c7d24a5c9, ChangeTrackingUpdateSpyTrait is a better place to assert on operations performed by ChangeTrackingEventIngress than DerivedPageDataUpdaterTest. What: - Add an expected number of enqueued CategoryMembershipChangeJobs to ChangeTrackingUpdateSpyTrait. - Update tests using the trait to specify the expected number of jobs. - Clear hooks in relevant tests to avoid test failures when extensions are loaded that attempt to call methods on the mocks set by ChangeTrackingUpdateSpyTrait. These tests currently fail if e.g. PageTriage, Echo or EventBus are loaded. Bug: T390636 Change-Id: I6fe6cb87cd5a16b1ed39e0998c49713704633d71
* | | storage: Push CategoryMembershipChangeJob in ChangeTrackingEventIngressMáté Szabó2025-04-042-4/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Why: - CategoryMembershipChangeJob is currently enqueued in DerivedPageDataUpdater. - This job is responsible for creating RC entries for category membership changes that resulted from an edit, so it is semantically a better fit for ChangeTrackingEventIngress instead. - Idf6625d3e737e4a225648b0fd81cc929b095d315 unintentionally changed the logic to enqueue this job for both direct content changes and reconciliation requests, rather than only direct content changes. Since the job creates RC entries, it should only be enqueued as a result of direct content changes. What: - Move the logic of enqueueing CategoryMembershipChangeJobs into ChangeTrackingEventIngress. - Only enqueue CategoryMembershipChangeJobs for direct content changes and update tests accordingly. - Resolve the old TODO of making this logic MCR-aware by checking whether any changed content slot supports categories as a precondition of enqueueing the job, rather than only checking the main slot. Bug: T390636 Change-Id: Icfe33ccc6cfa391e65ecae21d8c1d575dc247ee3
* | | storage: Test DerivedPageDataUpdate behavior around null editsMáté Szabó2025-04-041-9/+86
|/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Why: - Idf6625d3e737e4a225648b0fd81cc929b095d315 changed DerivedPageDataUpdater to enqueue CategoryMembershipChangeJobs for "nominal content changes", i.e. if the current change actually changed the page content or was a "reconciliation request". - In DE parlance, null edits are considered to be a form of "reconciliation request". - CategoryMembershipChangeJob is responsible for generating RC entries for each category membership change that resulted from an edit, with some added heavy lifting to handle multiple edits that occurred in quick succession inside a single job. It therefore is not intended to run in the context of a reconciliation request, be it a null edit or something else, and is better suited to be enqueued from ChangeTrackingEventIngress rather than DerivedPageDataUpdater. - Before we make this change, it would be valuable to add test coverage around null edit handling in DerivedPageDataUpdater and to assert on a CategoryMembershipChangeJob being enqueued as needed. What: - Expand DerivedPageDataUpdater integration tests to cover page creation and null edits. - Add an assertion checking that a CategoryMembershipChangeJob is enqueued (or not) as needed. Bug: T390636 Change-Id: I14944639e00407f59380c8787fd2810c7d24a5c9
* | Bump wikimedia/parsoid to 0.21.0-a24C. Scott Ananian2025-04-041-11/+10
| | | | | | | | | | | | | | | | | | Contains tweaks to keep phan happy with the more precise property types introduced in Parsoid upstream in this release. Bug: T391042 Depends-On: Ibcf6d7ae272a27905f80390a1b8e2a609d31f6ab Change-Id: Ib475a2b82d9faccec1c5752fa6d941f8cc849ed7
* | Merge "Stats: Fix "MediaWiki.PHPUnit.AssertEquals.Int" in UnitTestingHelperTest"jenkins-bot2025-04-041-4/+2
|\ \
| * | Stats: Fix "MediaWiki.PHPUnit.AssertEquals.Int" in UnitTestingHelperTestTimo Tijhof2025-04-031-4/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Follows-up I1b9435dcdacd952b, which introduced this and silenced the warning, but it appears this warning is spot-on: > $ composer phpcs > … > assertEquals accepts many non-zero values, please use strict alternatives like > assertSame (MediaWiki.PHPUnit.AssertEquals.Int) We don't want to tolerate something like this: ``` var_dump(1 == true); class Foo{} var_dump(1 == new Foo()); var_dump(1 == (object)[]); var_dump(1 == new stdClass); var_dump(1 == '01.0'); var_dump(1 == '01.'); var_dump(1 == '01'); var_dump(1 == '1'); ``` Bug: T368740 Change-Id: Ib3966b96f65d41b1d320ae043dcbea1a445a55f5
* | | In .htaccess deny files, use "Satisfy All"Tim Starling2025-04-042-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | These .htaccess files are intended to prohibit all web access. But if the user sets "Satisfy Any" on a parent directory, in conjunction with any permissive require directive like "Require all granted", access will be allowed despite "Require all denied" in .htaccess. So, override Satisfy so that the "Require all denied" will reliably take effect. Note that "Satisfy All" is the default. This only affects non-default installations. Change-Id: Ia5862fb69e439b7ea2ed7af011e1ebf8f1b1f6d6
* | | Merge "DomainEvent: rename EventIngressBase to DomainEventIngress"jenkins-bot2025-04-042-7/+7
|\ \ \
| * | | DomainEvent: rename EventIngressBase to DomainEventIngressAaron Schulz2025-04-032-7/+7
| | | | | | | | | | | | | | | | | | | | Bug: T390735 Change-Id: I0ebec537bb15925e8507ee6934cd4a17973c536a
* | | | SpecialBlock [Codex]: Include an 'Active range blocks' table for IPsMusikAnimal2025-04-033-0/+135
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When the target is an IP or IP range, show an 'Active range blocks' accordion that lists all range blocks that apply to the target. The idea is that admins should be informed if an IP or range is already blocked, even if the target is a wider CIDR range. Each row in the table has a 'View' link to load that range as the target. We do this instead of providing direct 'Edit' / 'Remove' links because admins may not realize the range block is for a different target. In effect, 'Active range blocks' surfaces blocks that effect the target, but not directly. The 'Active range blocks' accordion is always shown for IPs and ranges (situations where there could be active range blocks) but has an empty state like the other tables. Bug: T389987 Change-Id: I4d5f42984b05cf1b30e2f962b9381779196fcab3
* | | | Merge "globalcontributions: Tolerate trailing spaces on special:contributions"jenkins-bot2025-04-031-0/+42
|\ \ \ \ | |/ / / |/| | |
| * | | globalcontributions: Tolerate trailing spaces on special:contributionsHéctor Arroyo2025-04-031-0/+42
| | |/ | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Why: - When accessing Special:GlobalContributions, if the target to look for ends with a whitespace, the page returns no results, showing an error stating that the target is not a valid user name instead. To test it, you can provide a target ending with a whitespace in the URL, like ?title=Special:GlobalContributions&target=172.22.0.1+&namespace=all (note the plus sign at the end of the target). - When accessing the page, different code paths seem to expect having the user name provided in different ways (reading it from the request itself, getting it passed as a value, or reading it from the controller's $opts attribute). What: - Cleanup the target before the actual logic for the contributions special pages starts, making all contributions pages (including global contributions) read the user name after stripping the leading and trailing whitespaces, if any. Bug: T378279 Change-Id: I9f6a0d70d2d967cf5ec33c77bffa89c90fb81e25
* | | Merge "UserLookup.vue: trigger new search when changes are made before mounting"jenkins-bot2025-04-023-1/+35
|\ \ \
| * | | UserLookup.vue: trigger new search when changes are made before mountingMusikAnimal2025-04-013-1/+35
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Given the Lookup component a template ref and force a lookup and display the results when the user types in something before Vue loads. A TODO is left for making the test assert that the menu is visible. Related: T390127 Move refs to the top of setup() and document them to be consistent with the structure of other components as well as the store. SpecialBlock.php: if the Codex form is submitted, treat as no-submission since this code path isn't supposed to be possible with a JS-only form. Bug: T389955 Change-Id: I6b9788370495648f1629ec7c3b768e704d78f157
* | | | Merge "Parsoid Fragment Support v3: make mStripExtTags a persistent Parser ↵jenkins-bot2025-04-021-1/+1
|\ \ \ \ | | | | | | | | | | | | | | | property"
| * | | | Parsoid Fragment Support v3: make mStripExtTags a persistent Parser propertyC. Scott Ananian2025-04-021-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Rather than reset `Parser::$mStripExtTags` after post-processing, ensure that it is `false` for any frame expansion done using the legacy parser kept by Parsoid's DataAccess. This was causing issues with Extension:Babel, which was invoking $parser->replaceVariables() recursively when the {{#babel}} parser function was expanded by Parsoid. This new behavior is enabled by setting $wgParsoidFragmentSupport to 'v3', in order to allow us to run round-trip testing with this configuration without disturbing production. The configuration variable is temporary, and will be cleaned up in Ib5365c87ab594a2c21a84ec8bc2a64a71799085f. Bug: T390420 Change-Id: I8f45ea027776c3bb0c9f4468afa00465e41b6dec
* | | | | Merge "Special:Block [Codex]: Pressing enter should submit the form"jenkins-bot2025-04-021-0/+17
|\ \ \ \ \ | |/ / / / |/| | | |
| * | | | Special:Block [Codex]: Pressing enter should submit the formhmonroy2025-03-261-0/+17
| | | | | | | | | | | | | | | | | | | | | | | | | Bug: T388007 Change-Id: I1c91a94a37837b230e2ad0f6a0c58ac29c9271e8
* | | | | Merge "Client-side date/time formatter library"jenkins-bot2025-04-024-0/+473
|\ \ \ \ \ | |_|_|/ / |/| | | |
| * | | | Client-side date/time formatter libraryTim Starling2025-04-024-0/+473
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add a library providing date/time formatting according to the user's preferred time zone and date preference. I tested formatting of an example date with all defined formats in all languages, and I found that it gives identical output to PHP in about 90% of our ~500 languages. Resolve some of the outstanding issues by aliasing the problematic date formats on the client side, so that the user will see the date in another acceptable format for the same language. The remaining issues mostly relate to the use of a fallback language to display weekdays and non-Gregorian month names. Details: * Add Language::getJsDateFormats(), which converts existing date formats to an options array that can be interpreted by the client. * In Messages*.php, add $numberingSystem, which is the CLDR numbering system ID. I set it for all languages that had overriden $digitTransformTable. This is sent to the client in the library's JSON config and is used as the default numberingSystem option when formatting dates. * In Messages*.php, add $jsDateFormats, which overrides the automatically generated date format options. Bug: T389161 Change-Id: Ib6bc8ebd4d01317aaf32225c6006ea2dc7a1b39e
* | | | | Merge "block: Add autoblock filtering parameters"jenkins-bot2025-04-021-0/+40
|\ \ \ \ \ | |/ / / / |/| | | |
| * | | | block: Add autoblock filtering parametersTim Starling2025-03-211-0/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add $auto parameter to DatabaseBlockStore::newFromTarget and ::newListFromTarget, to help callers filter autoblocks from result lists. Change-Id: Iad92d205517eb50ab0ce5e8caae58ee761fe19d5
* | | | | Merge "ParserCache: Skip saving of "redirect=no" ParserOutput of redirect pages"jenkins-bot2025-04-011-193/+834
|\ \ \ \ \
| * | | | | ParserCache: Skip saving of "redirect=no" ParserOutput of redirect pagesdaniel2025-04-011-193/+834
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Why: - ParserCache refuses to return cache entries for redirect pages. So we shouldn't write these entries into the parser cache in the first place. - If we write but refuse to read, this means there will be a cache write every time a redirect page is retrieved via ParserOutputAccess. What: - Make ParserCache:save() skip entries for redirect pages. This is only reachable via "redirect=no" since by default MediaWiki pageviews render the destination page instead. Note: - It seems we should be able to store redirect pages like any other page in the ParserCache. Why we didn't, and whether we should, is not yet clear. While this is being investigated we should establish consistent behavior for get() and save(). Bug: T389591 Change-Id: I880997193d6de66121c902de80a77c1305bd01d3
* | | | | | Merge "tests: Use more trivial no-op and null implementations"jenkins-bot2025-04-012-9/+3
|\ \ \ \ \ \ | |_|_|_|_|/ |/| | | | |
| * | | | | tests: Use more trivial no-op and null implementationsthiemowmde2025-04-012-9/+3
| | |_|/ / | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | There are dedicated classes and methods for this. No need to redo the same manually. Change-Id: I75f5c1f0911f5fcdc63414943747cb3fca664a8e
* | | | | Merge "wdio-mediawiki: Release 2.7.1"jenkins-bot2025-04-012-1/+6
|\ \ \ \ \
| * | | | | wdio-mediawiki: Release 2.7.1James D. Forrester2025-04-012-1/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Bug: T381727 Bug: T389536 Bug: T389562 Change-Id: If7d858ce69582cbec2ceaaf82dcd22bcf3d9e202
* | | | | | tests: Use type declaration on undocumented private functionsUmherirrender2025-03-3017-29/+31
| | | | | | | | | | | | | | | | | | | | | | | | Change-Id: I56b31870ce9be46d15fcd9095f9a12e0f2488ed9
* | | | | | Merge "ParserTestRunner: register magic words from Parsoid's test runner"jenkins-bot2025-03-301-6/+40
|\ \ \ \ \ \
| * | | | | | ParserTestRunner: register magic words from Parsoid's test runnerC. Scott Ananian2025-03-281-6/+40
| | |_|/ / / | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Parsoid has a set of Parsoid-specific native fragment handlers it registers for parser tests; ensure the magic words for these are registered before running parser tests. Change-Id: Ib4e697f30d02a2e460e818cbde591fbe1bafd6fa
* | | | | | Merge "ResourceLoader: Remove unused 'dir' parameter to load.php"jenkins-bot2025-03-283-28/+10
|\ \ \ \ \ \
| * | | | | | ResourceLoader: Remove unused 'dir' parameter to load.phpTimo Tijhof2025-03-253-28/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When MediaWiki creates load.php URLs, in OutputPage and via RL\Client, it sets 'lang', not 'dir'. The direction is automatically derived from the language, which makes the library easier to use for developers, and also avoids a potentially confusing scenario in which the two are different (e.g. lang=he and dir=ltr would not make sense, and would further risk poisoning LTR content in an RTL/Hebrew-related cache somewhere). Bug: T225845 Change-Id: I14905c85bb5e3bb47a681dc99668b92844d22f04
* | | | | | | Localize duration number in Watchlist editorHuji2025-03-281-7/+23
| |/ / / / / |/| | | | | | | | | | | | | | | | | | | | | | | Bug: T387255 Change-Id: I3c39db9d8394254b94f0828de0df4fb57e8d49e7
* | | | | | Merge "ResourceLoader: Reject module names starting with "./" && "../""jenkins-bot2025-03-271-0/+7
|\ \ \ \ \ \