tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

parseQuery.js (6231B)


      1 /**
      2 * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
      3 **/import { assert } from '../../util/util.js';import {
      4 
      5  badParamValueChars,
      6  paramKeyIsPublic } from
      7 '../params_utils.js';
      8 
      9 import { parseParamValue } from './json_param_value.js';
     10 import {
     11 
     12  TestQueryMultiFile,
     13  TestQueryMultiTest,
     14  TestQueryMultiCase,
     15  TestQuerySingleCase } from
     16 './query.js';
     17 import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './separators.js';
     18 import { validQueryPart } from './validQueryPart.js';
     19 
     20 /**
     21 * converts foo/bar/src/webgpu/this/that/file.spec.ts to webgpu:this,that,file,*
     22 */
     23 function convertPathToQuery(path) {
     24  // removes .spec.ts and splits by directory separators.
     25  const parts = path.substring(0, path.length - 8).split(/\/|\\/g);
     26  // Gets parts only after the last `src`. Example: returns ['webgpu', 'foo', 'bar', 'test']
     27  // for ['Users', 'me', 'src', 'cts', 'src', 'webgpu', 'foo', 'bar', 'test']
     28  const partsAfterSrc = parts.slice(parts.lastIndexOf('src') + 1);
     29  const suite = partsAfterSrc.shift();
     30  return `${suite}:${partsAfterSrc.join(',')},*`;
     31 }
     32 
     33 /**
     34 * If a query looks like a path (ends in .spec.ts and has directory separators)
     35 * then convert try to convert it to a query.
     36 */
     37 function convertPathLikeToQuery(queryOrPath) {
     38  return queryOrPath.endsWith('.spec.ts') && (
     39  queryOrPath.includes('/') || queryOrPath.includes('\\')) ?
     40  convertPathToQuery(queryOrPath) :
     41  queryOrPath;
     42 }
     43 
     44 /**
     45 * Convert long suite names (the part before the first colon) to the
     46 * shortest last word
     47 *    foo.bar.moo:test,subtest,foo -> moo:test,subtest,foo
     48 */
     49 function shortenSuiteName(query) {
     50  const parts = query.split(':');
     51  // converts foo.bar.moo to moo
     52  const suite = parts.shift()?.replace(/.*\.(\w+)$/, '$1');
     53  return [suite, ...parts].join(':');
     54 }
     55 
     56 export function parseQuery(queryLike) {
     57  try {
     58    const query = shortenSuiteName(convertPathLikeToQuery(queryLike));
     59    return parseQueryImpl(query);
     60  } catch (ex) {
     61    if (ex instanceof Error) {
     62      ex.message += `\n  on: ${queryLike}`;
     63    }
     64    throw ex;
     65  }
     66 }
     67 
     68 function parseQueryImpl(s) {
     69  // Undo encodeURIComponentSelectively
     70  s = decodeURIComponent(s);
     71 
     72  // bigParts are: suite, file, test, params (note kBigSeparator could appear in params)
     73  let suite;
     74  let fileString;
     75  let testString;
     76  let paramsString;
     77  {
     78    const i1 = s.indexOf(kBigSeparator);
     79    assert(i1 !== -1, `query string must have at least one ${kBigSeparator}`);
     80    suite = s.substring(0, i1);
     81    const i2 = s.indexOf(kBigSeparator, i1 + 1);
     82    if (i2 === -1) {
     83      fileString = s.substring(i1 + 1);
     84    } else {
     85      fileString = s.substring(i1 + 1, i2);
     86      const i3 = s.indexOf(kBigSeparator, i2 + 1);
     87      if (i3 === -1) {
     88        testString = s.substring(i2 + 1);
     89      } else {
     90        testString = s.substring(i2 + 1, i3);
     91        paramsString = s.substring(i3 + 1);
     92      }
     93    }
     94  }
     95 
     96  const { parts: file, wildcard: filePathHasWildcard } = parseBigPart(fileString, kPathSeparator);
     97 
     98  if (testString === undefined) {
     99    // Query is file-level
    100    assert(
    101      filePathHasWildcard,
    102      `File-level query without wildcard ${kWildcard}. Did you want a file-level query \
    103 (append ${kPathSeparator}${kWildcard}) or test-level query (append ${kBigSeparator}${kWildcard})?`
    104    );
    105    return new TestQueryMultiFile(suite, file);
    106  }
    107  assert(!filePathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`);
    108 
    109  const { parts: test, wildcard: testPathHasWildcard } = parseBigPart(testString, kPathSeparator);
    110 
    111  if (paramsString === undefined) {
    112    // Query is test-level
    113    assert(
    114      testPathHasWildcard,
    115      `Test-level query without wildcard ${kWildcard}; did you want a test-level query \
    116 (append ${kPathSeparator}${kWildcard}) or case-level query (append ${kBigSeparator}${kWildcard})?`
    117    );
    118    assert(file.length > 0, 'File part of test-level query was empty (::)');
    119    return new TestQueryMultiTest(suite, file, test);
    120  }
    121 
    122  // Query is case-level
    123  assert(!testPathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`);
    124 
    125  const { parts: paramsParts, wildcard: paramsHasWildcard } = parseBigPart(
    126    paramsString,
    127    kParamSeparator
    128  );
    129 
    130  assert(test.length > 0, 'Test part of case-level query was empty (::)');
    131 
    132  const params = {};
    133  for (const paramPart of paramsParts) {
    134    const [k, v] = parseSingleParam(paramPart);
    135    assert(validQueryPart.test(k), `param key names must match ${validQueryPart}`);
    136    params[k] = v;
    137  }
    138  if (paramsHasWildcard) {
    139    return new TestQueryMultiCase(suite, file, test, params);
    140  } else {
    141    return new TestQuerySingleCase(suite, file, test, params);
    142  }
    143 }
    144 
    145 // webgpu:a,b,* or webgpu:a,b,c:*
    146 const kExampleQueries = `\
    147 webgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}${kWildcard} or \
    148 webgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}c${kBigSeparator}${kWildcard}`;
    149 
    150 function parseBigPart(
    151 s,
    152 separator)
    153 {
    154  if (s === '') {
    155    return { parts: [], wildcard: false };
    156  }
    157  const parts = s.split(separator);
    158 
    159  let endsWithWildcard = false;
    160  for (const [i, part] of parts.entries()) {
    161    if (i === parts.length - 1) {
    162      endsWithWildcard = part === kWildcard;
    163    }
    164    assert(
    165      part.indexOf(kWildcard) === -1 || endsWithWildcard,
    166      `Wildcard ${kWildcard} must be complete last part of a path (e.g. ${kExampleQueries})`
    167    );
    168  }
    169  if (endsWithWildcard) {
    170    // Remove the last element of the array (which is just the wildcard).
    171    parts.length = parts.length - 1;
    172  }
    173  return { parts, wildcard: endsWithWildcard };
    174 }
    175 
    176 function parseSingleParam(paramSubstring) {
    177  assert(paramSubstring !== '', 'Param in a query must not be blank (is there a trailing comma?)');
    178  const i = paramSubstring.indexOf('=');
    179  assert(i !== -1, 'Param in a query must be of form key=value');
    180  const k = paramSubstring.substring(0, i);
    181  assert(paramKeyIsPublic(k), 'Param in a query must not be private (start with _)');
    182  const v = paramSubstring.substring(i + 1);
    183  return [k, parseSingleParamValue(v)];
    184 }
    185 
    186 function parseSingleParamValue(s) {
    187  assert(
    188    !badParamValueChars.test(s),
    189    `param value must not match ${badParamValueChars} - was ${s}`
    190  );
    191  return parseParamValue(s);
    192 }