clone(incomingRelations) {
    if (incomingRelations && !this.assetGraph) {
      throw new Error(
        "asset.clone(): incomingRelations not supported because asset isn't in a graph"
      );
    }
    // TODO: Clone more metadata
    const constructorOptions = {
      isInitial: this.isInitial,
      _toBeMinified: this._toBeMinified,
      isPretty: this.isPretty,
      isDirty: this.isDirty,
      extension: this.extension,
      lastKnownByteLength: this.lastKnownByteLength,
      serializationOptions: this.serializationOptions && {
        ...this.serializationOptions,
      },
    };
    if (this.type === 'JavaScript' || this.type === 'Css') {
      if (this._parseTree) {
        constructorOptions.parseTree = this._cloneParseTree();
        if (typeof this._text === 'string') {
          constructorOptions.text = this._text;
        }
        if (this._rawSrc) {
          constructorOptions.rawSrc = this._rawSrc;
        }
      } else {
        const sourceMap = this.sourceMap;
        if (sourceMap) {
          constructorOptions.sourceMap = sourceMap;
        }
      }
    } else if (this.isText) {
      // Cheaper than encoding + decoding
      constructorOptions.text = this.text;
    } else {
      constructorOptions.rawSrc = this.rawSrc;
    }
    if (this._isFragment !== undefined) {
      // FIXME: Belongs in the subclass
      constructorOptions._isFragment = this._isFragment;
    }
    if (this.type === 'JavaScript') {
      // FIXME: Belongs in the subclass
      if (this.initialComments) {
        constructorOptions.initialComments = this.initialComments;
      }
      constructorOptions.isRequired = this.isRequired;
    }
    if (!this.isInline) {
      let nextSuffixToTry = 0;
      const baseName = this.baseName || this.id;
      const extension = this.extension || this.defaultExtension;
      do {
        constructorOptions.url = this.assetGraph.resolveUrl(
          this.url,
          baseName + (nextSuffixToTry ? `-${nextSuffixToTry}` : '') + extension
        );
        nextSuffixToTry += 1;
      } while (this.assetGraph._urlIndex[constructorOptions.url]);
    }
    const clone = new this.constructor(constructorOptions, this.assetGraph);

    this.assetGraph.addAsset(clone);
    if (!this.isInline) {
      clone.externalize(this.url);
    }
    if (incomingRelations) {
      if (!Array.isArray(incomingRelations)) {
        incomingRelations = [incomingRelations];
      }
      for (const incomingRelation of incomingRelations) {
        if (!incomingRelation || !incomingRelation.isRelation) {
          throw new Error(
            `asset.clone(): Incoming relation is not a relation: ${incomingRelation.toString()}`
          );
        }
        incomingRelation.to = clone;
      }
    }
    return clone;
  }
Clone this asset instance and add the clone to the graph if
this instance is part of a graph. As an extra service,
optionally update some caller-specified relations to point at
the clone.

If this instance isn't inline, a url is made up for the clone.

@param {Relation[]|Relation} incomingRelations (optional) Some incoming relations that should be pointed at the clone.
@return {Asset} The cloned asset.