forked from ChromeDevTools/devtools-frontend
-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathdevtools_build.mjs
More file actions
109 lines (103 loc) · 3.31 KB
/
Copy pathdevtools_build.mjs
File metadata and controls
109 lines (103 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright 2025 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* Representation of the feature set that is configured for Chrome. This
* keeps track of enabled and disabled features and generates the correct
* combination of `--enable-features` / `--disable-features` command line
* flags.
*
* There are unit tests for this in `./devtools_build.test.mjs`.
*/
export class FeatureSet {
#disabled = new Set();
#enabled = new Map();
/**
* Disables the given `feature`.
*
* @param {string} feature the name of the feature to disable.
*/
disable(feature) {
this.#disabled.add(feature);
this.#enabled.delete(feature);
}
/**
* Enables the given `feature`, and optionally adds the `parameters` to it.
* For example:
* ```js
* featureSet.enable('DevToolsFreestyler', {patching: true});
* ```
* The parameters are additive.
*
* @param {string} feature the name of the feature to enable.
* @param {object} parameters the additional parameters to pass to it, in
* the form of key/value pairs.
*/
enable(feature, parameters = {}) {
this.#disabled.delete(feature);
if (!this.#enabled.has(feature)) {
this.#enabled.set(feature, Object.create(null));
}
for (const [key, value] of Object.entries(parameters)) {
this.#enabled.get(feature)[key] = value;
}
}
/**
* Merge the other `featureSet` into this.
*
* @param featureSet the other `FeatureSet` to apply.
*/
merge(featureSet) {
for (const feature of featureSet.#disabled) {
this.disable(feature);
}
for (const [feature, parameters] of featureSet.#enabled) {
this.enable(feature, parameters);
}
}
/**
* Yields the command line parameters to pass to the invocation of
* a Chrome binary for achieving the state of the feature set.
*/
* [Symbol.iterator]() {
const disabledFeatures = [...this.#disabled];
if (disabledFeatures.length) {
yield `--disable-features=${disabledFeatures.sort().join(',')}`;
}
const enabledFeatures = [...this.#enabled].map(([feature, parameters]) => {
parameters = Object.entries(parameters);
if (parameters.length) {
parameters = parameters.map(([key, value]) => `${key}/${value}`);
feature = `${feature}:${parameters.sort().join('/')}`;
}
return feature;
});
if (enabledFeatures.length) {
yield `--enable-features=${enabledFeatures.sort().join(',')}`;
}
}
static parse(text) {
const features = [];
for (const str of text.split(',')) {
const parts = str.split(':');
if (parts.length < 1 || parts.length > 2) {
throw new Error(`Invalid feature declaration '${str}'`);
}
const feature = parts[0];
const parameters = Object.create(null);
if (parts.length > 1) {
const args = parts[1].split('/');
if (args.length % 2 !== 0) {
throw new Error(`Invalid parameters '${parts[1]}' for feature ${feature}`);
}
for (let i = 0; i < args.length; i += 2) {
const key = args[i + 0];
const value = args[i + 1];
parameters[key] = value;
}
}
features.push({feature, parameters});
}
return features;
}
}