UNPKG

9.41 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright (c) 2019 The Polymer Project Authors. All rights reserved.
5 * This code may only be used under the BSD style license found at
6 * http://polymer.github.io/LICENSE.txt The complete set of authors may be found
7 * at http://polymer.github.io/AUTHORS.txt The complete set of contributors may
8 * be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by
9 * Google as part of the polymer project is also subject to an additional IP
10 * rights grant found at http://polymer.github.io/PATENTS.txt
11 */
12var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13 if (k2 === undefined) k2 = k;
14 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
15}) : (function(o, m, k, k2) {
16 if (k2 === undefined) k2 = k;
17 o[k2] = m[k];
18}));
19var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20 Object.defineProperty(o, "default", { enumerable: true, value: v });
21}) : function(o, v) {
22 o["default"] = v;
23});
24var __importStar = (this && this.__importStar) || function (mod) {
25 if (mod && mod.__esModule) return mod;
26 var result = {};
27 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
28 __setModuleDefault(result, mod);
29 return result;
30};
31Object.defineProperty(exports, "__esModule", { value: true });
32exports.parseHorizons = exports.urlFromLocalPath = exports.applyDefaults = exports.makeConfig = void 0;
33const fsExtra = __importStar(require("fs-extra"));
34const path = __importStar(require("path"));
35const browser_1 = require("./browser");
36const configfile_1 = require("./configfile");
37const defaults = __importStar(require("./defaults"));
38const github_1 = require("./github");
39const specs_1 = require("./specs");
40const util_1 = require("./util");
41async function makeConfig(opts) {
42 // These options are only controlled by flags.
43 const baseConfig = {
44 mode: (opts.manual === true ? 'manual' : 'automatic'),
45 jsonFile: opts['json-file'],
46 legacyJsonFile: opts['save'],
47 csvFileStats: opts['csv-file'],
48 csvFileRaw: opts['csv-file-raw'],
49 forceCleanNpmInstall: opts['force-clean-npm-install'],
50 githubCheck: opts['github-check'] ?
51 github_1.parseGithubCheckFlag(opts['github-check']) :
52 undefined,
53 remoteAccessibleHost: opts['remote-accessible-host'],
54 };
55 let config;
56 if (opts.config) {
57 if (opts.root !== undefined) {
58 throw new Error('--root cannot be specified when using --config');
59 }
60 if (opts.browser !== undefined) {
61 throw new Error('--browser cannot be specified when using --config');
62 }
63 if (opts['sample-size'] !== undefined) {
64 throw new Error('--sample-size cannot be specified when using --config');
65 }
66 if (opts.timeout !== undefined) {
67 throw new Error('--timeout cannot be specified when using --config');
68 }
69 if (opts.horizon !== undefined) {
70 throw new Error('--horizon cannot be specified when using --config');
71 }
72 if (opts.measure !== undefined) {
73 throw new Error('--measure cannot be specified when using --config');
74 }
75 if (opts['resolve-bare-modules'] !== undefined) {
76 throw new Error('--resolve-bare-modules cannot be specified when using --config');
77 }
78 if (opts['window-size'] !== undefined) {
79 throw new Error('--window-size cannot be specified when using --config');
80 }
81 const rawConfigObj = await fsExtra.readJson(opts.config);
82 const validatedConfigObj = await configfile_1.parseConfigFile(rawConfigObj);
83 await configfile_1.writeBackSchemaIfNeeded(rawConfigObj, opts.config);
84 config = applyDefaults(Object.assign(Object.assign({}, baseConfig), validatedConfigObj));
85 }
86 else {
87 config = applyDefaults(Object.assign(Object.assign({}, baseConfig), { root: opts.root, sampleSize: opts['sample-size'], timeout: opts.timeout, horizons: opts.horizon !== undefined ?
88 parseHorizons(opts.horizon.split(',')) :
89 undefined, benchmarks: await specs_1.specsFromOpts(opts), resolveBareModules: opts['resolve-bare-modules'] }));
90 }
91 if (config.sampleSize <= 1) {
92 throw new Error('--sample-size must be > 1');
93 }
94 if (config.timeout < 0) {
95 throw new Error('--timeout must be >= 0');
96 }
97 if (config.benchmarks.length === 0) {
98 throw new Error('No benchmarks matched with the given flags');
99 }
100 for (const spec of config.benchmarks) {
101 for (const measurement of spec.measurement) {
102 if (measurement.mode === 'performance' &&
103 measurement.entryName === 'first-contentful-paint' &&
104 !browser_1.fcpBrowsers.has(spec.browser.name)) {
105 throw new Error(`Browser ${spec.browser.name} does not support the ` +
106 `first contentful paint (FCP) measurement`);
107 }
108 }
109 }
110 return config;
111}
112exports.makeConfig = makeConfig;
113function applyDefaults(partial) {
114 return {
115 benchmarks: partial.benchmarks !== undefined ? partial.benchmarks : [],
116 csvFileStats: partial.csvFileStats !== undefined ? partial.csvFileStats :
117 '',
118 csvFileRaw: partial.csvFileRaw !== undefined ? partial.csvFileRaw : '',
119 forceCleanNpmInstall: partial.forceCleanNpmInstall !== undefined ?
120 partial.forceCleanNpmInstall :
121 defaults.forceCleanNpmInstall,
122 githubCheck: partial.githubCheck,
123 horizons: partial.horizons !== undefined ?
124 partial.horizons :
125 parseHorizons([...defaults.horizons]),
126 jsonFile: partial.jsonFile !== undefined ? partial.jsonFile : '',
127 legacyJsonFile: partial.legacyJsonFile !== undefined ? partial.legacyJsonFile : '',
128 sampleSize: partial.sampleSize !== undefined ? partial.sampleSize :
129 defaults.sampleSize,
130 mode: partial.mode !== undefined ? partial.mode : defaults.mode,
131 remoteAccessibleHost: partial.remoteAccessibleHost !== undefined ?
132 partial.remoteAccessibleHost :
133 '',
134 resolveBareModules: partial.resolveBareModules !== undefined ?
135 partial.resolveBareModules :
136 defaults.resolveBareModules,
137 root: partial.root !== undefined ? partial.root : defaults.root,
138 timeout: partial.timeout !== undefined ? partial.timeout : defaults.timeout,
139 };
140}
141exports.applyDefaults = applyDefaults;
142/**
143 * Derives the URL that we'll use to benchmark using the given HTML file or
144 * directory on disk, relative to the root directory we'll be serving. Throws if
145 * it's a file that doesn't exist, or a directory without an index.html.
146 */
147async function urlFromLocalPath(rootDir, diskPath) {
148 const serverRelativePath = path.relative(rootDir, diskPath);
149 if (serverRelativePath.startsWith('..')) {
150 throw new Error('File or directory is not accessible from server root: ' + diskPath);
151 }
152 const kind = await util_1.fileKind(diskPath);
153 if (kind === undefined) {
154 throw new Error(`No such file or directory: ${diskPath}`);
155 }
156 let urlPath = `/${serverRelativePath.replace(path.win32.sep, '/')}`;
157 if (kind === 'dir') {
158 if (await util_1.fileKind(path.join(diskPath, 'index.html')) !== 'file') {
159 throw new Error(`Directory did not contain an index.html: ${diskPath}`);
160 }
161 // We need a trailing slash when serving a directory. Our static server
162 // will serve index.html at both /foo and /foo/, without redirects. But
163 // these two forms will have baseURIs that resolve relative URLs
164 // differently, and we want the form that would work the same as
165 // /foo/index.html.
166 urlPath += '/';
167 }
168 return urlPath;
169}
170exports.urlFromLocalPath = urlFromLocalPath;
171/** Parse horizon flags into signed horizon values. */
172function parseHorizons(strs) {
173 const absolute = new Set();
174 const relative = new Set();
175 for (const str of strs) {
176 if (!str.match(/^[-+]?(\d*\.)?\d+(ms|%)$/)) {
177 throw new Error(`Invalid horizon ${str}`);
178 }
179 let num;
180 let absOrRel;
181 const isPercent = str.endsWith('%');
182 if (isPercent === true) {
183 num = Number(str.slice(0, -1)) / 100;
184 absOrRel = relative;
185 }
186 else {
187 // Otherwise ends with "ms".
188 num = Number(str.slice(0, -2)); // Note that Number("+1") === 1
189 absOrRel = absolute;
190 }
191 if (str.startsWith('+') || str.startsWith('-') || num === 0) {
192 // If the sign was explicit (e.g. "+0.1", "-0.1") then we're only
193 // interested in that signed horizon.
194 absOrRel.add(num);
195 }
196 else {
197 // Otherwise (e.g. "0.1") we're interested in the horizon as a
198 // difference in either direction.
199 absOrRel.add(-num);
200 absOrRel.add(num);
201 }
202 }
203 return {
204 absolute: [...absolute].sort((a, b) => a - b),
205 relative: [...relative].sort((a, b) => a - b),
206 };
207}
208exports.parseHorizons = parseHorizons;
209//# sourceMappingURL=config.js.map
\No newline at end of file