From 240429573263686f3882bb256c8431746bcf424a Mon Sep 17 00:00:00 2001 From: "Daniel D. Beck" Date: Tue, 3 Dec 2024 10:54:17 -0500 Subject: [PATCH 01/10] Add `discouraged` to schema --- index.ts | 9 +++++++++ schemas/data.schema.json | 24 ++++++++++++++++++++++++ scripts/dist.ts | 2 +- types.ts | 18 +++++++++++++++--- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/index.ts b/index.ts index 87d3eec680c..d7df26716bf 100644 --- a/index.ts +++ b/index.ts @@ -182,6 +182,15 @@ for (const [key, data] of yamlEntries('features')) { features[key] = data; } +// Assert that discouraged feature's alternatives are valid +for (const [id, feature] of Object.entries(features)) { + for (const alternative of feature.discouraged?.alternatives ?? []) { + if (!(alternative in features)) { + throw new Error(`${id}'s alternative "${alternative}" is not a valid feature ID`); + } + } +} + const compat = new Compat(); const browsers: Partial = {}; for (const browser of coreBrowserSet.map(identifier => compat.browser(identifier))) { diff --git a/schemas/data.schema.json b/schemas/data.schema.json index 99363c4d78a..7e456997ab5 100644 --- a/schemas/data.schema.json +++ b/schemas/data.schema.json @@ -57,6 +57,30 @@ "description": "Short description of the feature, as an HTML string", "type": "string" }, + "discouraged": { + "additionalProperties": false, + "description": "Whether developers are formally discouraged from using this feature", + "properties": { + "according_to": { + "description": "Links to a formal discouragement notice, such as specification text, intent-to-unship, etc.", + "items": { + "description": "URI", + "format": "uri", + "type": "string" + }, + "type": "array" + }, + "alternatives": { + "description": "IDs for features that substitute some or all of this feature's utility", + "items": {}, + "type": "array" + } + }, + "required": [ + "according_to" + ], + "type": "object" + }, "group": { "anyOf": [ { diff --git a/scripts/dist.ts b/scripts/dist.ts index e664a0f52a4..cf96bfa289c 100644 --- a/scripts/dist.ts +++ b/scripts/dist.ts @@ -233,7 +233,7 @@ function toDist(sourcePath: string): YAML.Document { checkAncestors: true, }); - if (computedStatus.discouraged) { + if (computedStatus.discouraged && !source.discouraged) { const isDraft: boolean = source.draft_date ?? false; if (!source.draft_date) { diff --git a/types.ts b/types.ts index 6d51e26b912..e223bcb2861 100644 --- a/types.ts +++ b/types.ts @@ -45,6 +45,8 @@ export interface FeatureData { status: SupportStatus; /** Sources of support data for this feature */ compat_features?: string[]; + /** Whether developers are formally discouraged from using this feature */ + discouraged?: Discouraged; } type BrowserIdentifier = "chrome" | "chrome_android" | "edge" | "firefox" | "firefox_android" | "safari" | "safari_ios"; @@ -69,10 +71,20 @@ interface SupportStatus extends Status { by_compat_key?: Record } -/** Specification URL +interface Discouraged { + /** Links to a formal discouragement notice, such as specification text, intent-to-unship, etc. */ + according_to: uri[]; + /** IDs for features that substitute some or all of this feature's utility */ + alternatives?: (keyof WebFeaturesData["features"])[]; +} + +/** URI * @format uri -*/ -type specification_url = string; + */ +type uri = string; + +/** Specification URL */ +type specification_url = uri; export interface GroupData { /** Short name */ From 99cd5025d2bff980475c4efa3e476c44f64da23a Mon Sep 17 00:00:00 2001 From: "Daniel D. Beck" Date: Tue, 3 Dec 2024 10:54:39 -0500 Subject: [PATCH 02/10] Add discouraged `with` statement feature --- features/symbol.yml | 1 - features/symbol.yml.dist | 13 ----------- features/with.yml | 24 +++++++++++++++++++ features/with.yml.dist | 50 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 features/with.yml create mode 100644 features/with.yml.dist diff --git a/features/symbol.yml b/features/symbol.yml index 27724245217..400113c5230 100644 --- a/features/symbol.yml +++ b/features/symbol.yml @@ -23,6 +23,5 @@ compat_features: - javascript.builtins.Symbol.toString - javascript.builtins.Symbol.toStringTag - javascript.builtins.Symbol.toStringTag.dom_objects - - javascript.builtins.Symbol.unscopables - javascript.builtins.Symbol.valueOf - javascript.builtins.Symbol.@@toPrimitive diff --git a/features/symbol.yml.dist b/features/symbol.yml.dist index 3acc3ab911d..3a78a9fd7f5 100644 --- a/features/symbol.yml.dist +++ b/features/symbol.yml.dist @@ -45,19 +45,6 @@ compat_features: - javascript.builtins.Symbol.for - javascript.builtins.Symbol.keyFor - # baseline: high - # baseline_low_date: 2016-08-02 - # baseline_high_date: 2019-02-02 - # support: - # chrome: "38" - # chrome_android: "38" - # edge: "12" - # firefox: "48" - # firefox_android: "48" - # safari: "9" - # safari_ios: "9" - - javascript.builtins.Symbol.unscopables - # baseline: high # baseline_low_date: 2016-09-20 # baseline_high_date: 2019-03-20 diff --git a/features/with.yml b/features/with.yml new file mode 100644 index 00000000000..676c8e02072 --- /dev/null +++ b/features/with.yml @@ -0,0 +1,24 @@ +name: with +description: The `with` JavaScript statement adds a given object to the chain of scopes used to evaluate names. +spec: https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-with-statement +group: javascript +discouraged: + # One thing that is potentially missing here is a "reason" like this: + + # reason: browser-warning + # reason: spec-caution + # reason: pending-removal + + # This would allow us to signal to tools how "fatal" the discouragement is + # (e.g., pending-removal should trigger noisy errors for developers but spec + # caution would not). I'm not sure the full range of these yet; I think it + # might be easier to choose the set of reasons after we've enumerated a bunch + # of discouraged features. + according_to: + - https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-with-statement + alternatives: + - destructuring +compat_features: + - javascript.statements.with + - javascript.builtins.Symbol.unscopables + - javascript.builtins.Array.@@unscopables diff --git a/features/with.yml.dist b/features/with.yml.dist new file mode 100644 index 00000000000..0d116d6098f --- /dev/null +++ b/features/with.yml.dist @@ -0,0 +1,50 @@ +# Generated from: with.yml +# Do not edit this file by hand. Edit the source file instead! + +status: + baseline: false + support: + chrome: "38" + chrome_android: "38" + edge: "12" + firefox: "48" + firefox_android: "48" + safari: "10" + safari_ios: "10" +compat_features: + # baseline: high + # baseline_low_date: 2016-08-02 + # baseline_high_date: 2019-02-02 + # support: + # chrome: "38" + # chrome_android: "38" + # edge: "12" + # firefox: "48" + # firefox_android: "48" + # safari: "9" + # safari_ios: "9" + - javascript.builtins.Symbol.unscopables + + # baseline: high + # baseline_low_date: 2016-09-20 + # baseline_high_date: 2019-03-20 + # support: + # chrome: "38" + # chrome_android: "38" + # edge: "12" + # firefox: "48" + # firefox_android: "48" + # safari: "10" + # safari_ios: "10" + - javascript.builtins.Array.@@unscopables + + # baseline: false + # support: + # chrome: "1" + # chrome_android: "18" + # edge: "12" + # firefox: "1" + # firefox_android: "4" + # safari: "1" + # safari_ios: "1" + - javascript.statements.with From 855b48ec7286269e7f9bf5795ffc9c04d1fa59bc Mon Sep 17 00:00:00 2001 From: "Daniel D. Beck" Date: Thu, 12 Dec 2024 18:49:56 +0100 Subject: [PATCH 03/10] Remove unused variable Co-authored-by: James Stuckey Weber --- scripts/dist.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/dist.ts b/scripts/dist.ts index cf96bfa289c..bc06b72a433 100644 --- a/scripts/dist.ts +++ b/scripts/dist.ts @@ -234,7 +234,6 @@ function toDist(sourcePath: string): YAML.Document { }); if (computedStatus.discouraged && !source.discouraged) { - const isDraft: boolean = source.draft_date ?? false; if (!source.draft_date) { logger.error( From 308a3ef9bad584188d1e7af72ce24055643d2924 Mon Sep 17 00:00:00 2001 From: "Daniel D. Beck" Date: Thu, 12 Dec 2024 18:41:46 +0100 Subject: [PATCH 04/10] Add data guidelines for discouraged --- docs/guidelines.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/guidelines.md b/docs/guidelines.md index 289c4639561..1b70c461850 100644 --- a/docs/guidelines.md +++ b/docs/guidelines.md @@ -309,3 +309,42 @@ For example, don't assign a feature to both `css` and `fonts`, since `css` is th Do assign features to groups when there's an opportunity for future feature composition (see [#971](https://github.com/web-platform-dx/web-features/issues/971)). For example, several features for the JavaScript `Array` interface are members of the `array` group. + +## Discouraged + +Rarely, the developers should not use a platform feature because it's the consensus of relevant stakeholders (i.e., a standards body and implementers), even if that feature is still implemented in browsers. +Mark a feature as discouraged when: + +- The specification adopts clear language directing developers to stop using that feature or to prefer to an alternative. + This is often through terms like "deprecated", "obsolete", "legacy", or "non-standard." + They can also be in the form of one-off recommendations to use alternatives (such as "[…ought to be used instead](https://dom.spec.whatwg.org/#ref-for-concept-event%E2%91%A4%E2%91%A3)"). + +- The specification removes that feature from the specification without a succession plan (such as moving it to another specification). + +- The specification editors intend to discourage or remove the feature from the specification. + For example, meeting minutes show that a committee achieved consensus to remove a feature from a specification, even if the removal is not complete. + +- All of the (present) implementers issue warnings when using that feature or have published something expressing an intention to unship that feature. + + +Do not mark a feature as discouraged when: + +- The feature is merely old or unpopular, no matter how many [_considered harmful_](https://en.wikipedia.org/wiki/Considered_harmful) blog posts it may have garnered. + For example, despite the existence of `fetch`, `XMLHttpRequest` is not a discouraged feature. + +- The feature is controversial. + Opposition to a feature (without consensus) is not sufficient to mark a feature as discouraged. + For example, do not mark a feature as discouraged because a vendor has given it a negative standards position. + +- The feature is buggy or not implemented in one or more browsers. + Contribute to accurate support data instead. + +When you set a `discouraged` block in a feature file, do: + +- Set a (required) `according_to` URL, linking to evidence that the feature is discouraged. + If possible, use the single most broadly applicable reference, such as specification text. + If a feature is removed from a specification, link to an issue, pull request, or commit showing the removal. + +- Set one or more (optional) `alternative` feature IDs that are whole or partial substitutes for the discouraged feature. + An alternative doesn't have to be a narrow drop-in replacement for the discouraged feature but it must handle some use case of the discouraged feature. + Guide developers to the most relevant features that would help them stop using the discouraged feature. From 036e19e8d55ef713d7fef1fddec4cd0cd66eb260 Mon Sep 17 00:00:00 2001 From: "Daniel D. Beck" Date: Thu, 12 Dec 2024 18:48:39 +0100 Subject: [PATCH 05/10] Add discouraged usage guidelines --- packages/web-features/README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/web-features/README.md b/packages/web-features/README.md index f5df58ac202..7f9d8b00ddf 100644 --- a/packages/web-features/README.md +++ b/packages/web-features/README.md @@ -1,7 +1,5 @@ # Curated list of Web platform features -This package is experimental, expect frequent breaking changes! - ## Usage ```sh @@ -27,13 +25,18 @@ import schema from "web-features/data.schema.json" with { type: "json" }; ## Rendering Baseline statuses with `web-features` -If you're using `web-features` to render Baseline iconography or browser logos with support markers, then you must follow these procedures to ensure consistent usage. +If you're using `web-features` to render Baseline iconography or browser logos with support markers, then you must follow the [name and logo usage guidelines](https://web-platform-dx.github.io/web-features/name-and-logo-usage-guidelines/). For Baseline iconography, follow this procedure for each feature: 1. If `status.baseline` is `"high"`, then show an affirmative "widely available" icon. 1. If `status.baseline` is `"low"`, then show an affirmative "newly available" icon. 1. If `status.baseline` is `false`, then show a "limited availability" non-Baseline icon. + + **Note**: All features that have the `discouraged` property are, by definition, non-Baseline. + If a feature has the `discouraged` property, consider showing a message describing the feature's discouraged status instead of Baseline iconography. + Showing Baseline iconography for discouraged features may confuse readers. + 1. If `status.baseline` is `undefined`, then **do not** show any Baseline or non-Baseline badge. For browser support iconography (that is, browser logos and checkmarks and Xs), follow this procedure for each browser: From 78311b662cbaa02140f0702681e07c462dd5e6ff Mon Sep 17 00:00:00 2001 From: "Daniel D. Beck" Date: Thu, 12 Dec 2024 19:30:52 +0100 Subject: [PATCH 06/10] Apply prettier fixes --- features/with.yml | 2 +- scripts/dist.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/features/with.yml b/features/with.yml index 676c8e02072..42a797ed2ce 100644 --- a/features/with.yml +++ b/features/with.yml @@ -8,7 +8,7 @@ discouraged: # reason: browser-warning # reason: spec-caution # reason: pending-removal - + # This would allow us to signal to tools how "fatal" the discouragement is # (e.g., pending-removal should trigger noisy errors for developers but spec # caution would not). I'm not sure the full range of these yet; I think it diff --git a/scripts/dist.ts b/scripts/dist.ts index bc06b72a433..8c1c6f4fe80 100644 --- a/scripts/dist.ts +++ b/scripts/dist.ts @@ -234,7 +234,6 @@ function toDist(sourcePath: string): YAML.Document { }); if (computedStatus.discouraged && !source.discouraged) { - if (!source.draft_date) { logger.error( `${id}: contains at least one deprecated compat feature. This is forbidden for published features.`, From 3a5896b565819dfb075bdfe139c920bb09e6afad Mon Sep 17 00:00:00 2001 From: "Daniel D. Beck" Date: Fri, 13 Dec 2024 09:52:44 +0100 Subject: [PATCH 07/10] Relate `discouraged` to `status.baseline` more explicitly Co-authored-by: James Stuckey Weber --- packages/web-features/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-features/README.md b/packages/web-features/README.md index 7f9d8b00ddf..72876cda114 100644 --- a/packages/web-features/README.md +++ b/packages/web-features/README.md @@ -33,7 +33,7 @@ For Baseline iconography, follow this procedure for each feature: 1. If `status.baseline` is `"low"`, then show an affirmative "newly available" icon. 1. If `status.baseline` is `false`, then show a "limited availability" non-Baseline icon. - **Note**: All features that have the `discouraged` property are, by definition, non-Baseline. + **Note**: All features that have the `discouraged` property are, by definition, non-Baseline, and `status.baseline` will be `false`. If a feature has the `discouraged` property, consider showing a message describing the feature's discouraged status instead of Baseline iconography. Showing Baseline iconography for discouraged features may confuse readers. From eb62063142a6317210033dbef3dba2d46bcfb7a5 Mon Sep 17 00:00:00 2001 From: "Daniel D. Beck" Date: Fri, 13 Dec 2024 10:07:07 +0100 Subject: [PATCH 08/10] Find out why CI is passing --- index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/index.ts b/index.ts index d7df26716bf..3dd78dc4470 100644 --- a/index.ts +++ b/index.ts @@ -185,6 +185,7 @@ for (const [key, data] of yamlEntries('features')) { // Assert that discouraged feature's alternatives are valid for (const [id, feature] of Object.entries(features)) { for (const alternative of feature.discouraged?.alternatives ?? []) { + console.log(`Confirming ${alternative} in feature set`); if (!(alternative in features)) { throw new Error(`${id}'s alternative "${alternative}" is not a valid feature ID`); } From fc94af6beac7a6f53ed19977961ddf452f14a9bc Mon Sep 17 00:00:00 2001 From: "Daniel D. Beck" Date: Mon, 16 Dec 2024 17:31:31 +0100 Subject: [PATCH 09/10] Remove `non-standard` from spec language bullet --- docs/guidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guidelines.md b/docs/guidelines.md index 1b70c461850..8003d09b30d 100644 --- a/docs/guidelines.md +++ b/docs/guidelines.md @@ -316,7 +316,7 @@ Rarely, the developers should not use a platform feature because it's the consen Mark a feature as discouraged when: - The specification adopts clear language directing developers to stop using that feature or to prefer to an alternative. - This is often through terms like "deprecated", "obsolete", "legacy", or "non-standard." + This is often through terms like "deprecated", "obsolete", or "legacy." They can also be in the form of one-off recommendations to use alternatives (such as "[…ought to be used instead](https://dom.spec.whatwg.org/#ref-for-concept-event%E2%91%A4%E2%91%A3)"). - The specification removes that feature from the specification without a succession plan (such as moving it to another specification). From d1dbb46dadddb797bfeab58f7a9ff1f1d7f3ddb6 Mon Sep 17 00:00:00 2001 From: "Daniel D. Beck" Date: Mon, 16 Dec 2024 18:29:46 +0100 Subject: [PATCH 10/10] Refresh schema --- schemas/data.schema.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/schemas/data.schema.json b/schemas/data.schema.json index cea444ba338..520a84e8341 100644 --- a/schemas/data.schema.json +++ b/schemas/data.schema.json @@ -64,8 +64,6 @@ "according_to": { "description": "Links to a formal discouragement notice, such as specification text, intent-to-unship, etc.", "items": { - "description": "URI", - "format": "uri", "type": "string" }, "type": "array"