SingleMapping.fromJson constructor

SingleMapping.fromJson(
  1. Map<String, dynamic> map, {
  2. dynamic mapUrl,
})

Implementation

SingleMapping.fromJson(Map<String, dynamic> map, {mapUrl})
    : targetUrl = map['file'] as String?,
      urls = List<String>.from(map['sources'] as List),
      names = List<String>.from((map['names'] as List?) ?? []),
      files = List.filled((map['sources'] as List).length, null),
      sourceRoot = map['sourceRoot'] as String?,
      lines = <TargetLineEntry>[],
      _mapUrl = mapUrl is String ? Uri.parse(mapUrl) : (mapUrl as Uri?),
      extensions = {} {
  var sourcesContent = map['sourcesContent'] == null
      ? const <String?>[]
      : List<String?>.from(map['sourcesContent'] as List);
  for (var i = 0; i < urls.length && i < sourcesContent.length; i++) {
    var source = sourcesContent[i];
    if (source == null) continue;
    files[i] = SourceFile.fromString(source, url: urls[i]);
  }

  var line = 0;
  var column = 0;
  var srcUrlId = 0;
  var srcLine = 0;
  var srcColumn = 0;
  var srcNameId = 0;
  var tokenizer = _MappingTokenizer(map['mappings'] as String);
  var entries = <TargetEntry>[];

  while (tokenizer.hasTokens) {
    if (tokenizer.nextKind.isNewLine) {
      if (entries.isNotEmpty) {
        lines.add(TargetLineEntry(line, entries));
        entries = <TargetEntry>[];
      }
      line++;
      column = 0;
      tokenizer._consumeNewLine();
      continue;
    }

    // Decode the next entry, using the previous encountered values to
    // decode the relative values.
    //
    // We expect 1, 4, or 5 values. If present, values are expected in the
    // following order:
    //   0: the starting column in the current line of the generated file
    //   1: the id of the original source file
    //   2: the starting line in the original source
    //   3: the starting column in the original source
    //   4: the id of the original symbol name
    // The values are relative to the previous encountered values.
    if (tokenizer.nextKind.isNewSegment) throw _segmentError(0, line);
    column += tokenizer._consumeValue();
    if (!tokenizer.nextKind.isValue) {
      entries.add(TargetEntry(column));
    } else {
      srcUrlId += tokenizer._consumeValue();
      if (srcUrlId >= urls.length) {
        throw StateError(
            'Invalid source url id. $targetUrl, $line, $srcUrlId');
      }
      if (!tokenizer.nextKind.isValue) throw _segmentError(2, line);
      srcLine += tokenizer._consumeValue();
      if (!tokenizer.nextKind.isValue) throw _segmentError(3, line);
      srcColumn += tokenizer._consumeValue();
      if (!tokenizer.nextKind.isValue) {
        entries.add(TargetEntry(column, srcUrlId, srcLine, srcColumn));
      } else {
        srcNameId += tokenizer._consumeValue();
        if (srcNameId >= names.length) {
          throw StateError('Invalid name id: $targetUrl, $line, $srcNameId');
        }
        entries.add(
            TargetEntry(column, srcUrlId, srcLine, srcColumn, srcNameId));
      }
    }
    if (tokenizer.nextKind.isNewSegment) tokenizer._consumeNewSegment();
  }
  if (entries.isNotEmpty) {
    lines.add(TargetLineEntry(line, entries));
  }

  map.forEach((name, value) {
    if (name.startsWith('x_')) extensions[name] = value;
  });
}