-
Notifications
You must be signed in to change notification settings - Fork 630
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: print warning on use of deprecated API (#4200)
* feat: `warnDeprecatedApi()` * refactor: fixes and tweaks * refactor: tweaks and improvements * refactor: further work * refactor * fix * tweaks * tweak * tweak * tweaks * tweak * add test * tweaks * make compatible with Deploy * tweak * fix
- Loading branch information
Showing
5 changed files
with
169 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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
This file contains 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,9 @@ | ||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. | ||
|
||
/** | ||
* Internal utilities for the public API of the Deno Standard Library. | ||
* | ||
* Note: for internal use only. | ||
* | ||
* @module | ||
*/ |
This file contains 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,97 @@ | ||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
|
||
// deno-lint-ignore no-explicit-any | ||
const { Deno } = globalThis as any; | ||
|
||
const ALREADY_WARNED_DEPRECATED = new Set<string>(); | ||
const ENV_VAR_KEY = "DENO_NO_DEPRECATION_WARNINGS"; | ||
const shouldDisableDeprecatedApiWarning = | ||
Deno?.permissions.querySync?.({ name: "env", variable: ENV_VAR_KEY }) | ||
.state === "granted" && Deno?.env.get(ENV_VAR_KEY) === "1"; | ||
|
||
interface WarnDeprecatedApiConfig { | ||
/** The name of the deprecated API. */ | ||
apiName: string; | ||
/** The stack trace of the deprecated API. */ | ||
stack: string; | ||
/** The version in which the API will be removed. */ | ||
removalVersion: string; | ||
/** An optional message to print. */ | ||
suggestion?: string; | ||
} | ||
|
||
/** | ||
* Prints a warning message to the console for the given deprecated API. | ||
* | ||
* These warnings can be disabled by setting `DENO_NO_DEPRECATION_WARNINGS=1` | ||
* in the current process. | ||
* | ||
* Mostly copied from | ||
* {@link https://github.com/denoland/deno/blob/c62615bfe5a070c2517f3af3208d4308c72eb054/runtime/js/99_main.js#L101}. | ||
*/ | ||
export function warnOnDeprecatedApi(config: WarnDeprecatedApiConfig) { | ||
if (shouldDisableDeprecatedApiWarning) return; | ||
|
||
const key = config.apiName + config.stack; | ||
if (ALREADY_WARNED_DEPRECATED.has(key)) return; | ||
|
||
// If we haven't warned yet, let's do some processing of the stack trace | ||
// to make it more useful. | ||
const stackLines = config.stack.split("\n"); | ||
stackLines.shift(); | ||
|
||
let isFromRemoteDependency = false; | ||
const firstStackLine = stackLines[0]; | ||
if (firstStackLine && !firstStackLine.includes("file:")) { | ||
isFromRemoteDependency = true; | ||
} | ||
|
||
ALREADY_WARNED_DEPRECATED.add(key); | ||
console.log( | ||
"%cWarning", | ||
"color: yellow; font-weight: bold;", | ||
); | ||
console.log( | ||
`%c\u251c Use of deprecated "${config.apiName}" API.`, | ||
"color: yellow;", | ||
); | ||
console.log("%c\u2502", "color: yellow;"); | ||
console.log( | ||
`%c\u251c This API will be removed in version ${config.removalVersion} of the Deno Standard Library.`, | ||
"color: yellow;", | ||
); | ||
console.log("%c\u2502", "color: yellow;"); | ||
console.log( | ||
`%c\u251c Suggestion: ${config.suggestion}`, | ||
"color: yellow;", | ||
); | ||
if (isFromRemoteDependency) { | ||
console.log("%c\u2502", "color: yellow;"); | ||
console.log( | ||
`%c\u251c Suggestion: It appears this API is used by a remote dependency.`, | ||
"color: yellow;", | ||
); | ||
console.log( | ||
"%c\u2502 Try upgrading to the latest version of that dependency.", | ||
"color: yellow;", | ||
); | ||
} | ||
|
||
console.log("%c\u2502", "color: yellow;"); | ||
console.log( | ||
"%c\u251c Set `DENO_NO_DEPRECATION_WARNINGS=1` to disable these deprecation warnings.", | ||
"color: yellow;", | ||
); | ||
console.log("%c\u2502", "color: yellow;"); | ||
console.log("%c\u2514 Stack trace:", "color: yellow;"); | ||
for (let i = 0; i < stackLines.length; i++) { | ||
console.log( | ||
`%c ${i == stackLines.length - 1 ? "\u2514" : "\u251c"}\u2500 ${ | ||
stackLines[i].trim() | ||
}`, | ||
"color: yellow;", | ||
); | ||
} | ||
console.log(); | ||
} |
This file contains 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,49 @@ | ||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. | ||
import { assertEquals } from "../assert/assert_equals.ts"; | ||
import { warnOnDeprecatedApi } from "./warn_on_deprecated_api.ts"; | ||
|
||
Deno.test("warnDeprecatedApi()", async () => { | ||
const command = new Deno.Command(Deno.execPath(), { | ||
args: ["run", "--quiet", "--no-lock", import.meta.url], | ||
stderr: "inherit", | ||
}); | ||
const { success, stdout } = await command.output(); | ||
const output = new TextDecoder().decode(stdout); | ||
|
||
assertEquals(success, true); | ||
assertEquals( | ||
output, | ||
`Warning | ||
├ Use of deprecated "fn()" API. | ||
│ | ||
├ This API will be removed in version 1.0.0 of the Deno Standard Library. | ||
│ | ||
├ Suggestion: Do something else instead. | ||
│ | ||
├ Set \`DENO_NO_DEPRECATION_WARNINGS=1\` to disable these deprecation warnings. | ||
│ | ||
└ Stack trace: | ||
├─ at fn (${import.meta.url}:39:12) | ||
└─ at ${import.meta.url}:47:31 | ||
Hello, world! | ||
Hello, world! | ||
END | ||
`, | ||
); | ||
}); | ||
|
||
function fn() { | ||
warnOnDeprecatedApi({ | ||
apiName: "fn()", | ||
stack: new Error().stack!, | ||
removalVersion: "1.0.0", | ||
suggestion: "Do something else instead.", | ||
}); | ||
console.log("Hello, world!"); | ||
} | ||
|
||
if (import.meta.main) { | ||
for (let i = 0; i < 2; i++) fn(); | ||
console.log("END"); | ||
} |
This file contains 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