Page MenuHomePhabricator

Deprecate and remove `ParserFirstCallInit` hook (move hook/tag registration out of Parser constructor)
Open, Needs TriagePublic

Description

We would like to make Parser construction as speedy as possible. Calling the ParserFirstCallInit hook to register every single parser function and extension tag on every single parser object instantiation (as is now done) is a waste: 99.9% percent of extension and parser functions are available in every constructed parser, so we keep building the same maps and tables of tags and functions again and again.

Instead, extension and parser function registration should be via the standard ExtensionRegistry, and the hook/tag extension API should give extensions/parser functions the ability to 'nope out' of expansion if the tag/function is supposed to be disabled in that parser context. (This latter functionality will rarely be the right thing to do, since it's going to end up splatting the tag/function text literally on the page, but it might be necessary for, say, security or access control reasons.)

Note that this doesn't directly give you the ability to, say, have multiple extensions implement the <foo> tag, with one or the other registered during parser construction time. That's fine: just create a single shared <foo> implementation which calls a hook to dispatch to one or the other implementation dynamically. (Or just Don't Do That.) We might optionally change the extension mechanism to allow multi-maps from extension/tag name to implementation to allow fallback, but this seems like unnecessary complexity at this time.

See also T250444: Deprecate and remove Parser::firstCallInit(), which is about removing the Parser::firstCallInit method. This is about removing the hook.

Event Timeline

cscott renamed this task from Make Parsoid hook/tag registration global, instead of in Parser constructor to Deprecate and remove `ParserFirstCallInit` hook (move hook/tag registration out of Parser constructor).Jan 19 2022, 3:13 PM
cscott updated the task description. (Show Details)

Because there are some legacy extensions that may deliberately register a parser function or extension tag *only* in a specific context, our "expand this extension tag/parser function" API should explicitly have a "skip this registration and look for another" return value. That way those legacy extensions can (in the new system) *always* register the extension tag/parser function, but return the "skip this registration" value in all cases except those of the specific context in which it wants to be active.

Luckily, this pattern does not appear to be widespread, but it's still probably worth accommodating in the API to ease migration.