Files
react-native-devtools-frontend/scripts/devtools_build.mjs
T
Benedikt Meurer 1022e32645 [npm] Allow to select (unstable) features with npm start.
This adds an option `--enable-unstable-features`, which now also turns
on multimodal support for Freestyler.

It also adds `--enable-features` and `--disable-features`, to allow more
fine-grained control over the exact feature set when necessary.

Fixed: 406941932
Change-Id: I7fcecbba833a2e0a66166890aa5af218ae2a8f7e
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6404318
Reviewed-by: Nikolay Vitkov <nvitkov@chromium.org>
2025-03-28 06:40:16 -07:00

110 lines
3.3 KiB
JavaScript

// 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;
}
}