Remove prototype wrangling for String formatters

They are now moved to the StringUtilities file. Sadly, `String.sprintf`
is still used in the TestRunners that can't use ES modules.

The Multimap required exporting, as the NetworkManager has a reference
to it as well.

Bug: 1050549
Change-Id: Ia7b38dc212282a9800ee8c3083dac7f4a5e046e1
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2067057
Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org>
Reviewed-by: Jack Franklin <jacktfranklin@chromium.org>
This commit is contained in:
Tim van der Lippe
2020-02-20 18:15:46 +00:00
committed by Commit Bot
parent b1f2b6cce6
commit 93b57c3bbc
21 changed files with 274 additions and 236 deletions
+6 -4
View File
@@ -28,6 +28,7 @@
import * as Common from '../common/common.js';
import * as Host from '../host/host.js';
import * as Platform from '../platform/platform.js';
import * as SDK from '../sdk/sdk.js';
import * as UI from '../ui/ui.js';
@@ -414,7 +415,8 @@ export class Spectrum extends UI.Widget.VBox {
*/
_createPaletteColor(colorText, colorName, animationDelay) {
const element = createElementWithClass('div', 'spectrum-palette-color');
element.style.background = String.sprintf('linear-gradient(%s, %s), url(Images/checker.png)', colorText, colorText);
element.style.background =
Platform.StringUtilities.sprintf('linear-gradient(%s, %s), url(Images/checker.png)', colorText, colorText);
if (animationDelay) {
element.animate([{opacity: 0}, {opacity: 1}], {duration: 100, delay: animationDelay, fill: 'backwards'});
}
@@ -1018,8 +1020,8 @@ export class Spectrum extends UI.Widget.VBox {
this._colorDragElement.style.backgroundColor =
/** @type {string} */ (this._color().asString(Common.Color.Format.RGBA));
const noAlpha = Common.Color.Color.fromHSVA(this._hsv.slice(0, 3).concat(1));
this._alphaElementBackground.style.backgroundImage =
String.sprintf('linear-gradient(to right, rgba(0,0,0,0), %s)', noAlpha.asString(Common.Color.Format.RGB));
this._alphaElementBackground.style.backgroundImage = Platform.StringUtilities.sprintf(
'linear-gradient(to right, rgba(0,0,0,0), %s)', noAlpha.asString(Common.Color.Format.RGB));
}
_formatViewSwitch() {
@@ -1061,7 +1063,7 @@ export class Spectrum extends UI.Widget.VBox {
} else {
const format = this._colorFormat === cf.RGB ? 'rgba' : 'hsla';
const values = this._textValues.map(elementValue).join(', ');
colorString = String.sprintf('%s(%s)', format, values);
colorString = Platform.StringUtilities.sprintf('%s(%s)', format, values);
}
const color = Common.Color.Color.parse(colorString);
+2
View File
@@ -17,4 +17,6 @@ ts_library("trie") {
ts_library("color") {
sources = [ "Color.js" ]
deps = [ "../platform" ]
}
+10 -8
View File
@@ -27,6 +27,8 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import * as Platform from '../platform/platform.js';
/** @type {?Map<string, string>} */
let _rgbaToNickname;
@@ -579,10 +581,10 @@ export class Color {
if (this.hasAlpha()) {
return null;
}
return String.sprintf(
return Platform.StringUtilities.sprintf(
'rgb(%d, %d, %d)', toRgbValue(this._rgba[0]), toRgbValue(this._rgba[1]), toRgbValue(this._rgba[2]));
case Format.RGBA:
return String.sprintf(
return Platform.StringUtilities.sprintf(
'rgba(%d, %d, %d, %f)', toRgbValue(this._rgba[0]), toRgbValue(this._rgba[1]), toRgbValue(this._rgba[2]),
this._rgba[3]);
case Format.HSL:
@@ -590,15 +592,15 @@ export class Color {
return null;
}
const hsl = this.hsla();
return String.sprintf(
return Platform.StringUtilities.sprintf(
'hsl(%d, %d%, %d%)', Math.round(hsl[0] * 360), Math.round(hsl[1] * 100), Math.round(hsl[2] * 100));
case Format.HSLA:
const hsla = this.hsla();
return String.sprintf(
return Platform.StringUtilities.sprintf(
'hsla(%d, %d%, %d%, %f)', Math.round(hsla[0] * 360), Math.round(hsla[1] * 100), Math.round(hsla[2] * 100),
hsla[3]);
case Format.HEXA:
return String
return Platform.StringUtilities
.sprintf(
'#%s%s%s%s', toHexValue(this._rgba[0]), toHexValue(this._rgba[1]), toHexValue(this._rgba[2]),
toHexValue(this._rgba[3]))
@@ -607,7 +609,7 @@ export class Color {
if (this.hasAlpha()) {
return null;
}
return String
return Platform.StringUtilities
.sprintf('#%s%s%s', toHexValue(this._rgba[0]), toHexValue(this._rgba[1]), toHexValue(this._rgba[2]))
.toLowerCase();
case Format.ShortHEXA:
@@ -615,7 +617,7 @@ export class Color {
if (hexFormat !== Format.ShortHEXA && hexFormat !== Format.ShortHEX) {
return null;
}
return String
return Platform.StringUtilities
.sprintf(
'#%s%s%s%s', toShortHexValue(this._rgba[0]), toShortHexValue(this._rgba[1]),
toShortHexValue(this._rgba[2]), toShortHexValue(this._rgba[3]))
@@ -627,7 +629,7 @@ export class Color {
if (this.detectHEXFormat() !== Format.ShortHEX) {
return null;
}
return String
return Platform.StringUtilities
.sprintf(
'#%s%s%s', toShortHexValue(this._rgba[0]), toShortHexValue(this._rgba[1]),
toShortHexValue(this._rgba[2]))
+7 -4
View File
@@ -29,13 +29,15 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import * as Platform from '../platform/platform.js';
/**
* @param {string} string
* @param {...*} vararg
* @return {string}
*/
export function UIString(string, vararg) {
return String.vsprintf(localize(string), Array.prototype.slice.call(arguments, 1));
return Platform.StringUtilities.vsprintf(localize(string), Array.prototype.slice.call(arguments, 1));
}
/**
@@ -80,7 +82,8 @@ export class UIStringFormat {
/** @type {string} */
this._localizedFormat = localize(format);
/** @type {!Array.<!Object>} */
this._tokenizedFormat = String.tokenizeFormatString(this._localizedFormat, String.standardFormatters);
this._tokenizedFormat = Platform.StringUtilities.tokenizeFormatString(
this._localizedFormat, Platform.StringUtilities.standardFormatters);
}
/**
@@ -97,9 +100,9 @@ export class UIStringFormat {
* @return {string}
*/
format(vararg) {
return String
return Platform.StringUtilities
.format(
this._localizedFormat, arguments, String.standardFormatters, '', UIStringFormat._append,
this._localizedFormat, arguments, Platform.StringUtilities.standardFormatters, '', UIStringFormat._append,
this._tokenizedFormat)
.formattedResult;
}
+2 -1
View File
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import * as Common from '../common/common.js';
import * as Platform from '../platform/platform.js';
import * as UI from '../ui/ui.js';
export class ImagePreview {
@@ -72,7 +73,7 @@ export class ImagePreview {
}
if (imageURL !== originalImageURL) {
container.createChild('tr').createChild('td').createChild('span', 'description').textContent =
String.sprintf('currentSrc: %s', imageURL.trimMiddle(100));
Platform.StringUtilities.sprintf('currentSrc: %s', imageURL.trimMiddle(100));
}
fulfill(container);
}
+2 -1
View File
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import * as Common from '../common/common.js';
import * as Platform from '../platform/platform.js';
import * as SDK from '../sdk/sdk.js';
import * as TextUtils from '../text_utils/text_utils.js'; // eslint-disable-line no-unused-vars
import * as UI from '../ui/ui.js';
@@ -172,7 +173,7 @@ export class FilterTreeElement extends UI.TreeOutline.TreeElement {
} else if (this._messageCount === 1) {
this.title = _groupSingularTitleMap.get(this._filter.name);
} else {
this.title = String.sprintf(_groupPluralTitleMap.get(this._filter.name), this._messageCount);
this.title = Platform.StringUtilities.sprintf(_groupPluralTitleMap.get(this._filter.name), this._messageCount);
}
this.setExpandable(!!this.childCount());
+2 -1
View File
@@ -31,6 +31,7 @@ import * as Bindings from '../bindings/bindings.js';
import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as Host from '../host/host.js';
import * as Platform from '../platform/platform.js';
import * as SDK from '../sdk/sdk.js';
import * as TextUtils from '../text_utils/text_utils.js';
import * as UI from '../ui/ui.js';
@@ -760,7 +761,7 @@ export class ConsoleView extends UI.Widget.VBox {
async _saveConsole() {
const url = self.SDK.targetManager.mainTarget().inspectedURL();
const parsedURL = Common.ParsedURL.ParsedURL.fromString(url);
const filename = String.sprintf('%s-%d.log', parsedURL ? parsedURL.host : 'console', Date.now());
const filename = Platform.StringUtilities.sprintf('%s-%d.log', parsedURL ? parsedURL.host : 'console', Date.now());
const stream = new Bindings.FileUtils.FileOutputStream();
const progressIndicator = new UI.ProgressIndicator.ProgressIndicator();
+3 -2
View File
@@ -32,6 +32,7 @@ import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as DataGrid from '../data_grid/data_grid.js';
import * as ObjectUI from '../object_ui/object_ui.js';
import * as Platform from '../platform/platform.js';
import * as SDK from '../sdk/sdk.js';
import * as TextUtils from '../text_utils/text_utils.js';
import * as UI from '../ui/ui.js';
@@ -963,8 +964,8 @@ export class ConsoleViewMessage {
}
}
// String.format does treat formattedResult like a Builder, result is an object.
return String.format(format, parameters, formatters, formattedResult, append.bind(this));
// Platform.StringUtilities.format does treat formattedResult like a Builder, result is an object.
return Platform.StringUtilities.format(format, parameters, formatters, formattedResult, append.bind(this));
}
/**
+2 -1
View File
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import * as Common from '../common/common.js';
import * as Platform from '../platform/platform.js';
import * as SDK from '../sdk/sdk.js';
import * as UI from '../ui/ui.js';
import * as Workspace from '../workspace/workspace.js'; // eslint-disable-line no-unused-vars
@@ -122,7 +123,7 @@ export class MediaQueryInspector extends UI.Widget.Widget {
if (!uiLocation) {
continue;
}
const descriptor = String.sprintf(
const descriptor = Platform.StringUtilities.sprintf(
'%s:%d:%d', uiLocation.uiSourceCode.url(), uiLocation.lineNumber + 1, uiLocation.columnNumber + 1);
uiLocations.set(descriptor, uiLocation);
}
+2 -1
View File
@@ -32,6 +32,7 @@ import * as Bindings from '../bindings/bindings.js';
import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as Host from '../host/host.js';
import * as Platform from '../platform/platform.js';
import * as ProtocolModule from '../protocol/protocol.js'; // eslint-disable-line no-unused-vars
import * as SDK from '../sdk/sdk.js';
import * as TextUtils from '../text_utils/text_utils.js'; // eslint-disable-line no-unused-vars
@@ -1027,7 +1028,7 @@ export class ExtensionStatus {
const status = {code: code, description: description, details: details};
if (code !== 'OK') {
status.isError = true;
console.error('Extension server error: ' + String.vsprintf(description, details));
console.error('Extension server error: ' + Platform.StringUtilities.vsprintf(description, details));
}
return status;
}
@@ -27,6 +27,7 @@
import * as Common from '../common/common.js';
import * as Components from '../components/components.js'; // eslint-disable-line no-unused-vars
import * as Host from '../host/host.js';
import * as Platform from '../platform/platform.js';
import * as SDK from '../sdk/sdk.js';
import * as TextUtils from '../text_utils/text_utils.js';
import * as UI from '../ui/ui.js';
@@ -1178,7 +1179,7 @@ export class ArrayGroupingTreeElement extends UI.TreeOutline.TreeElement {
* @param {!Components.Linkifier.Linkifier=} linkifier
*/
constructor(object, fromIndex, toIndex, propertyCount, linkifier) {
super(String.sprintf('[%d \u2026 %d]', fromIndex, toIndex), true);
super(Platform.StringUtilities.sprintf('[%d \u2026 %d]', fromIndex, toIndex), true);
this.toggleOnClick = true;
this._fromIndex = fromIndex;
this._toIndex = toIndex;
+9
View File
@@ -0,0 +1,9 @@
import("../../third_party/typescript/typescript.gni")
ts_library("platform") {
sources = [
"platform.js",
"string-utilities.js",
"utilities.js",
]
}
+1
View File
@@ -32,4 +32,5 @@ import './utilities.js';
import * as StringUtilities from './string-utilities.js';
export {Multimap} from './utilities.js';
export {StringUtilities};
+202
View File
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @ts-nocheck
/**
* @param {string} inputString
* @param {string} charsToEscape
@@ -30,3 +32,203 @@ export const escapeCharacters = (inputString, charsToEscape) => {
return result;
};
/**
* @param {string} formatString
* @param {!Object.<string, function(string, ...):*>} formatters
* @return {!Array.<!Object>}
*/
export const tokenizeFormatString = function(formatString, formatters) {
const tokens = [];
function addStringToken(str) {
if (!str) {
return;
}
if (tokens.length && tokens[tokens.length - 1].type === 'string') {
tokens[tokens.length - 1].value += str;
} else {
tokens.push({type: 'string', value: str});
}
}
function addSpecifierToken(specifier, precision, substitutionIndex) {
tokens.push({type: 'specifier', specifier: specifier, precision: precision, substitutionIndex: substitutionIndex});
}
function addAnsiColor(code) {
const types = {3: 'color', 9: 'colorLight', 4: 'bgColor', 10: 'bgColorLight'};
const colorCodes = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'lightGray', '', 'default'];
const colorCodesLight =
['darkGray', 'lightRed', 'lightGreen', 'lightYellow', 'lightBlue', 'lightMagenta', 'lightCyan', 'white', ''];
const colors = {color: colorCodes, colorLight: colorCodesLight, bgColor: colorCodes, bgColorLight: colorCodesLight};
const type = types[Math.floor(code / 10)];
if (!type) {
return;
}
const color = colors[type][code % 10];
if (!color) {
return;
}
tokens.push({
type: 'specifier',
specifier: 'c',
value: {description: (type.startsWith('bg') ? 'background : ' : 'color: ') + color}
});
}
let textStart = 0;
let substitutionIndex = 0;
const re =
new RegExp(`%%|%(?:(\\d+)\\$)?(?:\\.(\\d*))?([${Object.keys(formatters).join('')}])|\\u001b\\[(\\d+)m`, 'g');
for (let match = re.exec(formatString); !!match; match = re.exec(formatString)) {
const matchStart = match.index;
if (matchStart > textStart) {
addStringToken(formatString.substring(textStart, matchStart));
}
if (match[0] === '%%') {
addStringToken('%');
} else if (match[0].startsWith('%')) {
// eslint-disable-next-line no-unused-vars
const [_, substitionString, precisionString, specifierString] = match;
if (substitionString && Number(substitionString) > 0) {
substitutionIndex = Number(substitionString) - 1;
}
const precision = precisionString ? Number(precisionString) : -1;
addSpecifierToken(specifierString, precision, substitutionIndex);
++substitutionIndex;
} else {
const code = Number(match[4]);
addAnsiColor(code);
}
textStart = matchStart + match[0].length;
}
addStringToken(formatString.substring(textStart));
return tokens;
};
/**
* @param {string} formatString
* @param {?ArrayLike} substitutions
* @param {!Object.<string, function(string, ...):Q>} formatters
* @param {!T} initialValue
* @param {function(T, Q): T|undefined} append
* @param {!Array.<!Object>=} tokenizedFormat
* @return {!{formattedResult: T, unusedSubstitutions: ?ArrayLike}};
* @template T, Q
*/
export const format = function(formatString, substitutions, formatters, initialValue, append, tokenizedFormat) {
if (!formatString || ((!substitutions || !substitutions.length) && formatString.search(/\u001b\[(\d+)m/) === -1)) {
return {formattedResult: append(initialValue, formatString), unusedSubstitutions: substitutions};
}
function prettyFunctionName() {
return 'String.format("' + formatString + '", "' + Array.prototype.join.call(substitutions, '", "') + '")';
}
function warn(msg) {
console.warn(prettyFunctionName() + ': ' + msg);
}
function error(msg) {
console.error(prettyFunctionName() + ': ' + msg);
}
let result = initialValue;
const tokens = tokenizedFormat || tokenizeFormatString(formatString, formatters);
const usedSubstitutionIndexes = {};
for (let i = 0; i < tokens.length; ++i) {
const token = tokens[i];
if (token.type === 'string') {
result = append(result, token.value);
continue;
}
if (token.type !== 'specifier') {
error('Unknown token type "' + token.type + '" found.');
continue;
}
if (!token.value && token.substitutionIndex >= substitutions.length) {
// If there are not enough substitutions for the current substitutionIndex
// just output the format specifier literally and move on.
error(
'not enough substitution arguments. Had ' + substitutions.length + ' but needed ' +
(token.substitutionIndex + 1) + ', so substitution was skipped.');
result = append(result, '%' + (token.precision > -1 ? token.precision : '') + token.specifier);
continue;
}
if (!token.value) {
usedSubstitutionIndexes[token.substitutionIndex] = true;
}
if (!(token.specifier in formatters)) {
// Encountered an unsupported format character, treat as a string.
warn('unsupported format character \u201C' + token.specifier + '\u201D. Treating as a string.');
result = append(result, token.value ? '' : substitutions[token.substitutionIndex]);
continue;
}
result = append(result, formatters[token.specifier](token.value || substitutions[token.substitutionIndex], token));
}
const unusedSubstitutions = [];
for (let i = 0; i < substitutions.length; ++i) {
if (i in usedSubstitutionIndexes) {
continue;
}
unusedSubstitutions.push(substitutions[i]);
}
return {formattedResult: result, unusedSubstitutions: unusedSubstitutions};
};
export const standardFormatters = {
/**
* @return {number}
*/
d: function(substitution) {
return !isNaN(substitution) ? substitution : 0;
},
/**
* @return {number}
*/
f: function(substitution, token) {
if (substitution && token.precision > -1) {
substitution = substitution.toFixed(token.precision);
}
return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
},
/**
* @return {string}
*/
s: function(substitution) {
return substitution;
}
};
/**
* @param {string} formatString
* @param {!Array.<*>} substitutions
* @return {string}
*/
export const vsprintf = function(formatString, substitutions) {
return format(formatString, substitutions, standardFormatters, '', function(a, b) {
return a + b;
}).formattedResult;
};
/**
* @param {string} format
* @param {...*} var_arg
* @return {string}
*/
export const sprintf = function(format, var_arg) {
return vsprintf(format, Array.prototype.slice.call(arguments, 1));
};
+8 -206
View File
@@ -26,6 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// @ts-nocheck
/* the long term goal here is to remove all functions in this file and
* replace them with ES Module functions rather than prototype
@@ -34,6 +35,10 @@
*/
import * as StringUtilities from './string-utilities.js';
// Still used in the test runners that can't use ES modules :(
String.sprintf = StringUtilities.sprintf;
/**
* @param {number} m
* @param {number} n
@@ -702,210 +707,6 @@ Object.defineProperty(Array.prototype, 'peekLast', {
});
})();
/**
* @param {string} format
* @param {...*} var_arg
* @return {string}
*/
String.sprintf = function(format, var_arg) {
return String.vsprintf(format, Array.prototype.slice.call(arguments, 1));
};
/**
* @param {string} format
* @param {!Object.<string, function(string, ...):*>} formatters
* @return {!Array.<!Object>}
*/
String.tokenizeFormatString = function(format, formatters) {
const tokens = [];
function addStringToken(str) {
if (!str) {
return;
}
if (tokens.length && tokens[tokens.length - 1].type === 'string') {
tokens[tokens.length - 1].value += str;
} else {
tokens.push({type: 'string', value: str});
}
}
function addSpecifierToken(specifier, precision, substitutionIndex) {
tokens.push({type: 'specifier', specifier: specifier, precision: precision, substitutionIndex: substitutionIndex});
}
function addAnsiColor(code) {
const types = {3: 'color', 9: 'colorLight', 4: 'bgColor', 10: 'bgColorLight'};
const colorCodes = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'lightGray', '', 'default'];
const colorCodesLight =
['darkGray', 'lightRed', 'lightGreen', 'lightYellow', 'lightBlue', 'lightMagenta', 'lightCyan', 'white', ''];
const colors = {color: colorCodes, colorLight: colorCodesLight, bgColor: colorCodes, bgColorLight: colorCodesLight};
const type = types[Math.floor(code / 10)];
if (!type) {
return;
}
const color = colors[type][code % 10];
if (!color) {
return;
}
tokens.push({
type: 'specifier',
specifier: 'c',
value: {description: (type.startsWith('bg') ? 'background : ' : 'color: ') + color}
});
}
let textStart = 0;
let substitutionIndex = 0;
const re =
new RegExp(`%%|%(?:(\\d+)\\$)?(?:\\.(\\d*))?([${Object.keys(formatters).join('')}])|\\u001b\\[(\\d+)m`, 'g');
for (let match = re.exec(format); !!match; match = re.exec(format)) {
const matchStart = match.index;
if (matchStart > textStart) {
addStringToken(format.substring(textStart, matchStart));
}
if (match[0] === '%%') {
addStringToken('%');
} else if (match[0].startsWith('%')) {
// eslint-disable-next-line no-unused-vars
const [_, substitionString, precisionString, specifierString] = match;
if (substitionString && Number(substitionString) > 0) {
substitutionIndex = Number(substitionString) - 1;
}
const precision = precisionString ? Number(precisionString) : -1;
addSpecifierToken(specifierString, precision, substitutionIndex);
++substitutionIndex;
} else {
const code = Number(match[4]);
addAnsiColor(code);
}
textStart = matchStart + match[0].length;
}
addStringToken(format.substring(textStart));
return tokens;
};
String.standardFormatters = {
/**
* @return {number}
*/
d: function(substitution) {
return !isNaN(substitution) ? substitution : 0;
},
/**
* @return {number}
*/
f: function(substitution, token) {
if (substitution && token.precision > -1) {
substitution = substitution.toFixed(token.precision);
}
return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
},
/**
* @return {string}
*/
s: function(substitution) {
return substitution;
}
};
/**
* @param {string} format
* @param {!Array.<*>} substitutions
* @return {string}
*/
String.vsprintf = function(format, substitutions) {
return String
.format(
format, substitutions, String.standardFormatters, '',
function(a, b) {
return a + b;
})
.formattedResult;
};
/**
* @param {string} format
* @param {?ArrayLike} substitutions
* @param {!Object.<string, function(string, ...):Q>} formatters
* @param {!T} initialValue
* @param {function(T, Q): T|undefined} append
* @param {!Array.<!Object>=} tokenizedFormat
* @return {!{formattedResult: T, unusedSubstitutions: ?ArrayLike}};
* @template T, Q
*/
String.format = function(format, substitutions, formatters, initialValue, append, tokenizedFormat) {
if (!format || ((!substitutions || !substitutions.length) && format.search(/\u001b\[(\d+)m/) === -1)) {
return {formattedResult: append(initialValue, format), unusedSubstitutions: substitutions};
}
function prettyFunctionName() {
return 'String.format("' + format + '", "' + Array.prototype.join.call(substitutions, '", "') + '")';
}
function warn(msg) {
console.warn(prettyFunctionName() + ': ' + msg);
}
function error(msg) {
console.error(prettyFunctionName() + ': ' + msg);
}
let result = initialValue;
const tokens = tokenizedFormat || String.tokenizeFormatString(format, formatters);
const usedSubstitutionIndexes = {};
for (let i = 0; i < tokens.length; ++i) {
const token = tokens[i];
if (token.type === 'string') {
result = append(result, token.value);
continue;
}
if (token.type !== 'specifier') {
error('Unknown token type "' + token.type + '" found.');
continue;
}
if (!token.value && token.substitutionIndex >= substitutions.length) {
// If there are not enough substitutions for the current substitutionIndex
// just output the format specifier literally and move on.
error(
'not enough substitution arguments. Had ' + substitutions.length + ' but needed ' +
(token.substitutionIndex + 1) + ', so substitution was skipped.');
result = append(result, '%' + (token.precision > -1 ? token.precision : '') + token.specifier);
continue;
}
if (!token.value) {
usedSubstitutionIndexes[token.substitutionIndex] = true;
}
if (!(token.specifier in formatters)) {
// Encountered an unsupported format character, treat as a string.
warn('unsupported format character \u201C' + token.specifier + '\u201D. Treating as a string.');
result = append(result, token.value ? '' : substitutions[token.substitutionIndex]);
continue;
}
result = append(result, formatters[token.specifier](token.value || substitutions[token.substitutionIndex], token));
}
const unusedSubstitutions = [];
for (let i = 0; i < substitutions.length; ++i) {
if (i in usedSubstitutionIndexes) {
continue;
}
unusedSubstitutions.push(substitutions[i]);
}
return {formattedResult: result, unusedSubstitutions: unusedSubstitutions};
};
/**
* @param {string} query
* @param {boolean} caseSensitive
@@ -1015,7 +816,7 @@ Map.prototype.inverse = function() {
/**
* @template K, V
*/
const Multimap = class {
export class Multimap {
constructor() {
/** @type {!Map.<K, !Set.<!V>>} */
this._map = new Map();
@@ -1115,7 +916,7 @@ const Multimap = class {
clear() {
this._map.clear();
}
};
}
/**
* @param {string} url
@@ -1176,6 +977,7 @@ Promise.prototype.catchException = function(defaultValue) {
/**
* TODO: move into its own module
* @param {function()} callback
* @suppressGlobalPropertiesCheck
*/
self.runOnWindowLoad = function(callback) {
/**
+2 -1
View File
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import * as HostModule from '../host/host.js';
import * as Platform from '../platform/platform.js';
import {cssMetadata, GridAreaRowRegex} from './CSSMetadata.js';
import {Edit} from './CSSModel.js'; // eslint-disable-line no-unused-vars
@@ -183,7 +184,7 @@ export class CSSProperty {
self.Common.settings.moduleSetting('textEditorIndent').get();
const endIndentation = this.ownerStyle.cssText ? indentation.substring(0, this.ownerStyle.range.endColumn) : '';
const text = new TextUtils.Text(this.ownerStyle.cssText || '');
const newStyleText = text.replaceRange(range, String.sprintf(';%s;', propertyText));
const newStyleText = text.replaceRange(range, Platform.StringUtilities.sprintf(';%s;', propertyText));
const tokenizerFactory = await self.runtime.extension(TextUtils.TokenizerFactory).instance();
const styleText = CSSProperty._formatStyle(newStyleText, indentation, endIndentation, tokenizerFactory);
+2 -1
View File
@@ -30,6 +30,7 @@
import * as Common from '../common/common.js';
import * as Host from '../host/host.js';
import * as Platform from '../platform/platform.js';
import * as ProtocolModule from '../protocol/protocol.js';
import {Cookie} from './Cookie.js';
@@ -1047,7 +1048,7 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
if (chromeMatch && chromeMatch.length > 1) {
// "1.2.3.4" becomes "1.0.100.0"
const additionalAppVersion = chromeMatch[1].split('.', 1)[0] + '.0.100.0';
return String.sprintf(uaString, chromeMatch[1], additionalAppVersion);
return Platform.StringUtilities.sprintf(uaString, chromeMatch[1], additionalAppVersion);
}
return uaString;
}
+2 -1
View File
@@ -27,6 +27,7 @@
*/
import * as Common from '../common/common.js';
import * as Platform from '../platform/platform.js';
import * as UI from '../ui/ui.js';
/**
@@ -64,7 +65,7 @@ export class FontView extends UI.View.SimpleView {
const {content} = deferredContent;
const url = content ? Common.ContentProvider.contentAsDataURL(content, this._mimeType, true) : this._url;
this.fontStyleElement.textContent =
String.sprintf('@font-face { font-family: "%s"; src: url(%s); }', uniqueFontName, url);
Platform.StringUtilities.sprintf('@font-face { font-family: "%s"; src: url(%s); }', uniqueFontName, url);
}
_createContentIfNeeded() {
+2 -1
View File
@@ -31,6 +31,7 @@
import * as ColorPicker from '../color_picker/color_picker.js';
import * as Common from '../common/common.js';
import * as InlineEditor from '../inline_editor/inline_editor.js';
import * as Platform from '../platform/platform.js';
import * as SDK from '../sdk/sdk.js';
import * as SourceFrame from '../source_frame/source_frame.js';
import * as TextUtils from '../text_utils/text_utils.js';
@@ -123,7 +124,7 @@ export class CSSPlugin extends Plugin {
return null;
}
const tail = unit.substring((unitValue).toString().length);
return String.sprintf('%d%s', unitValue + change, tail);
return Platform.StringUtilities.sprintf('%d%s', unitValue + change, tail);
}
/**
+3 -1
View File
@@ -33,6 +33,7 @@ import * as Bindings from '../bindings/bindings.js';
import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as PerfUI from '../perf_ui/perf_ui.js';
import * as Platform from '../platform/platform.js';
import * as SDK from '../sdk/sdk.js';
import * as TimelineModel from '../timeline_model/timeline_model.js';
import * as UI from '../ui/ui.js';
@@ -2496,7 +2497,8 @@ export class TimelineDetailsContentHelper {
return;
}
locationContent.appendChild(link);
locationContent.createTextChild(String.sprintf(' [%s\u2026%s]', startLine + 1, endLine + 1 || ''));
locationContent.createTextChild(
Platform.StringUtilities.sprintf(' [%s\u2026%s]', startLine + 1, endLine + 1 || ''));
this.appendElementRow(title, locationContent);
}
+3 -1
View File
@@ -32,6 +32,7 @@
import * as Common from '../common/common.js';
import * as Host from '../host/host.js';
import * as Platform from '../platform/platform.js';
import * as ARIAUtils from './ARIAUtils.js';
import {Dialog} from './Dialog.js';
@@ -711,7 +712,8 @@ export function formatLocalized(format, substitutions) {
a.appendChild(typeof b === 'string' ? createTextNode(b) : b);
return a;
}
return String.format(Common.UIString.UIString(format), substitutions, formatters, createElement('span'), append)
return Platform.StringUtilities
.format(Common.UIString.UIString(format), substitutions, formatters, createElement('span'), append)
.formattedResult;
}