toCodeString()

in scripts/endpoints-ruleset/compression-algorithms/PatternDetection.js [212:300]


  toCodeString(_export = this._export) {
    this.traverse();
    this.mode = "write";
    this.traverse();
    this.mode = "read";

    let buffer = "const _data=" + JSON.stringify(this.cloneData).replace(/"(\w+)":/g, `$1:`) + ";";

    // Write in this order: strings, objects, arrays.
    const orderedVariableIds = Object.keys(this.variableIdsUsed).sort((a, b) => {
      const boolStartChar = "b";
      let aStartChar = this.varIdToBlock[a].charAt(0);
      let bStartChar = this.varIdToBlock[b].charAt(0);

      aStartChar = aStartChar === "t" || aStartChar === "f" ? boolStartChar : aStartChar;
      bStartChar = bStartChar === "t" || bStartChar === "f" ? boolStartChar : bStartChar;

      if (aStartChar === bStartChar) {
        return 0;
      }

      for (const startChar of [`[`, `{`, `"`, boolStartChar]) {
        if (aStartChar === startChar) {
          return 1;
        } else if (bStartChar === startChar) {
          return -1;
        }
      }

      throw new Error(`unexpected start char: ${aStartChar}, ${bStartChar}`);
    });

    // code blocks
    let codeBlockBuffer = [];
    for (const variableId of orderedVariableIds) {
      const symbol = this.nextVariableName();
      const code = `${symbol}=${this.varIdToBlock[variableId]}`;
      codeBlockBuffer.push(code);
      buffer = buffer.replace(new RegExp(`"__REPLACE__${variableId}__REPLACE__"`, "g"), symbol);
    }

    for (let i = 0; i < codeBlockBuffer.length; ++i) {
      const iIndex = codeBlockBuffer[i].indexOf("=");
      const [iSymbol, iCode] = [codeBlockBuffer[i].slice(0, iIndex), codeBlockBuffer[i].slice(iIndex + 1)];

      for (let j = i + 1; j < codeBlockBuffer.length; ++j) {
        const jIndex = codeBlockBuffer[i].indexOf("=");
        const [, jCode] = [codeBlockBuffer[j].slice(0, jIndex), codeBlockBuffer[j].slice(jIndex + 1)];

        if (jCode.includes(iCode)) {
          if (iCode[0] !== '"' && iCode.length < 6) {
            // hack to prevent boolean literals from mistakenly being replaced in strings.
            continue;
          }

          codeBlockBuffer[j] = codeBlockBuffer[j].replaceAll(
            new RegExp(`${iCode.replaceAll(/([\[\]{}()])/g, `\\$1`)}:([^ ])`, "g"),
            `[${iSymbol}]:$1`
          );
          codeBlockBuffer[j] = codeBlockBuffer[j].replaceAll(iCode, iSymbol);
        }
      }
    }

    if (codeBlockBuffer.length > 0) {
      buffer = `const ` + codeBlockBuffer.join(",\n") + ";\n" + buffer;
    }

    // object keys
    let keyVarBuffer = [];
    for (const [key] of Object.entries(this.keyToVarId)) {
      const found = Array.from(buffer.matchAll(new RegExp(`"${key}":`, "g")) || []);

      if (found.length > 1 && key.length * found.length > 8) {
        const symbol = this.nextVariableName();
        keyVarBuffer.push(`${symbol}="${key}"`);
        buffer = buffer.replaceAll(new RegExp(`"?${key}"?:([^ ])`, "g"), `[${symbol}]:$1`);
      }
    }
    if (keyVarBuffer.length > 0) {
      buffer = "const " + keyVarBuffer.join(",\n") + ";\n" + buffer;
    }

    buffer += "\n";
    buffer += _export.replace("$", "_data");

    return buffer;
  }
};