Skip to content

Deprecated: Identify the culprit in the messaging #16842

Closed
@aduth

Description

@aduth

Currently, even if a user or developer is paying close attention to their browser's Console, they'd have a hard time acting upon a deprecation warning, unless they are operating within a very constrained environment (i.e. a single plugin and an assumption that Gutenberg itself would never violate any deprecations).

Instead, we should consider to make the messaging of a deprecation more actionable, specifically by naming the culprit and/or file from which the deprecation was caused. This way, a user could report the issue to the plugin author, or the plugin author could be more assured in observation that it's their code which requires change.

Task: Include the name of the plugin and/or file from the deprecation messaging.

Example:

Before:

wp.editor.withColors is deprecated and will be removed. Please use wp.blockEditor.withColors instead.

After:

wp.editor.withColors is deprecated and will be removed. Please use wp.blockEditor.withColors instead. This warning was caused by the Jetpack plugin (_inc/blocks/editor.js:13).

Implementation Notes:

The primary challenge is that in JavaScript, to the extent of my knowledge, we can't easily traverse up the caller stack to know from where the deprecated call was triggered.

There are a few things to work with:

  • Function#caller
    • Non-standard, forbidden in strict mode, likely not sufficient detail
  • console.trace
    • Logs directly to console, can't be captured
  • Error#stack
    • Non-standard, only accessible from context of a catch

As I see it, I think the most viable option would be to explore Error#stack as a progressive enhancement when available, using a faked thrown error. The output is a stack string, and it varies by browser, so it would need to be parsed in some form.

Example (Chrome):

Error
    at Object.deprecated (http://editor.test/wp-content/plugins/gutenberg/build/deprecated/index.js?ver=1564598972:135:11)
    at new PostTitle (http://editor.test/wp-content/plugins/gutenberg/build/editor/index.js?ver=1564598956:10213:8)
    at constructClassInstance (http://editor.test/wp-content/plugins/gutenberg/vendor/react-dom.165d5c53.js:11446:7)
    at updateClassComponent (http://editor.test/wp-content/plugins/gutenberg/vendor/react-dom.165d5c53.js:14776:5)
    at beginWork (http://editor.test/wp-content/plugins/gutenberg/vendor/react-dom.165d5c53.js:15733:16)
    at performUnitOfWork (http://editor.test/wp-content/plugins/gutenberg/vendor/react-dom.165d5c53.js:19401:12)
    at workLoop (http://editor.test/wp-content/plugins/gutenberg/vendor/react-dom.165d5c53.js:19441:24)
    at renderRoot (http://editor.test/wp-content/plugins/gutenberg/vendor/react-dom.165d5c53.js:19524:7)
    at performWorkOnRoot (http://editor.test/wp-content/plugins/gutenberg/vendor/react-dom.165d5c53.js:20431:7)
    at performWork (http://editor.test/wp-content/plugins/gutenberg/vendor/react-dom.165d5c53.js:20343:7)

Sample pseudo-code:

try {
	throw new Error;
} catch ( error ) {
	if ( typeof error.stack !== 'string' ) {
		return;
	}

	const file = error.stack.split( '\n' )[ 2 ].match( /\(([^)]+)\)$/ )[ 1 ];
	// "http://editor.test/wp-content/plugins/gutenberg/build/editor/index.js?ver=1564598956:10213:8"
}

If needed to back-reference the plugin, we could include a mapping of registered scripts from the server-side, including an (inferred perhaps also via debug_backtrace) origin plugin name from which the script was registered.

It would probably be much more complicated than this, since there might be multiple intermediaries between the plugin script and the Gutenberg code which calls deprecate (usually on some condition). Potentially then, we'd need to parse files line-by-line from the stack to find the first which matches a plugin path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Good First IssueAn issue that's suitable for someone looking to contribute for the first timeNeeds DevReady for, and needs developer efforts[Package] Deprecatedpackages/deprecated[Type] EnhancementA suggestion for improvement.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions