Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart

Issue 1617083002: Base JavaScript code position computation on JavaScript tracer. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library sourcemap.helper; 5 library sourcemap.helper;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'package:compiler/compiler_new.dart'; 8 import 'package:compiler/compiler_new.dart';
9 import 'package:compiler/src/apiimpl.dart' as api; 9 import 'package:compiler/src/apiimpl.dart' as api;
10 import 'package:compiler/src/null_compiler_output.dart' show NullSink; 10 import 'package:compiler/src/null_compiler_output.dart' show NullSink;
11 import 'package:compiler/src/elements/elements.dart'; 11 import 'package:compiler/src/elements/elements.dart';
12 import 'package:compiler/src/helpers/helpers.dart'; 12 import 'package:compiler/src/helpers/helpers.dart';
13 import 'package:compiler/src/filenames.dart'; 13 import 'package:compiler/src/filenames.dart';
14 import 'package:compiler/src/io/code_output.dart';
14 import 'package:compiler/src/io/source_file.dart'; 15 import 'package:compiler/src/io/source_file.dart';
15 import 'package:compiler/src/io/source_information.dart'; 16 import 'package:compiler/src/io/source_information.dart';
17 import 'package:compiler/src/io/position_information.dart';
16 import 'package:compiler/src/js/js.dart' as js; 18 import 'package:compiler/src/js/js.dart' as js;
17 import 'package:compiler/src/js/js_debug.dart'; 19 import 'package:compiler/src/js/js_debug.dart';
18 import 'package:compiler/src/js/js_source_mapping.dart'; 20 import 'package:compiler/src/js/js_source_mapping.dart';
19 import 'package:compiler/src/js_backend/js_backend.dart'; 21 import 'package:compiler/src/js_backend/js_backend.dart';
20 import 'package:compiler/src/source_file_provider.dart'; 22 import 'package:compiler/src/source_file_provider.dart';
21 import '../memory_compiler.dart'; 23 import '../memory_compiler.dart';
22 import '../output_collector.dart'; 24 import '../output_collector.dart';
23 25
26 class SourceFileSink implements EventSink<String> {
27 final String filename;
28 StringBuffer sb = new StringBuffer();
29 SourceFile sourceFile;
30
31 SourceFileSink(this.filename);
32
33 @override
34 void add(String event) {
35 sb.write(event);
36 }
37
38 @override
39 void addError(errorEvent, [StackTrace stackTrace]) {
40 // Ignore.
41 }
42
43 @override
44 void close() {
45 sourceFile = new StringSourceFile.fromName(filename, sb.toString());
46 }
47 }
48
24 class OutputProvider implements CompilerOutput { 49 class OutputProvider implements CompilerOutput {
25 BufferedEventSink jsMapOutput; 50 Map<Uri, SourceFileSink> outputMap = <Uri, SourceFileSink>{};
51
52 SourceFile getSourceFile(Uri uri) {
53 SourceFileSink sink = outputMap[uri];
54 if (sink != null) {
55 return sink.sourceFile;
56 }
57 return null;
58 }
59
60 SourceFileSink createSourceFileSink(String name, String extension) {
61 String filename = '$name.$extension';
62 SourceFileSink sink = new SourceFileSink(filename);
63 Uri uri = Uri.parse(filename);
64 outputMap[uri] = sink;
65 return sink;
66 }
26 67
27 @override 68 @override
28 EventSink<String> createEventSink(String name, String extension) { 69 EventSink<String> createEventSink(String name, String extension) {
29 if (extension == 'js.map') { 70 return createSourceFileSink(name, extension);
30 return jsMapOutput = new BufferedEventSink();
31 }
32 return new NullSink('$name.$extension');
33 } 71 }
34 } 72 }
35 73
36 class CloningOutputProvider extends OutputProvider { 74 class CloningOutputProvider extends OutputProvider {
37 RandomAccessFileOutputProvider outputProvider; 75 RandomAccessFileOutputProvider outputProvider;
38 76
39 CloningOutputProvider(Uri jsUri, Uri jsMapUri) 77 CloningOutputProvider(Uri jsUri, Uri jsMapUri)
40 : outputProvider = new RandomAccessFileOutputProvider(jsUri, jsMapUri); 78 : outputProvider = new RandomAccessFileOutputProvider(jsUri, jsMapUri);
41 79
42 @override 80 @override
43 EventSink<String> createEventSink(String name, String extension) { 81 EventSink<String> createEventSink(String name, String extension) {
44 EventSink<String> output = outputProvider(name, extension); 82 EventSink<String> output = outputProvider(name, extension);
45 if (extension == 'js.map') { 83 return new CloningEventSink(
46 output = new CloningEventSink( 84 [output, createSourceFileSink(name, extension)]);
47 [output, jsMapOutput = new BufferedEventSink()]);
48 }
49 return output;
50 } 85 }
51 } 86 }
52 87
53 abstract class SourceFileManager { 88 abstract class SourceFileManager {
54 SourceFile getSourceFile(var uri); 89 SourceFile getSourceFile(var uri);
55 } 90 }
56 91
57 class ProviderSourceFileManager implements SourceFileManager { 92 class ProviderSourceFileManager implements SourceFileManager {
58 final SourceFileProvider sourceFileProvider; 93 final SourceFileProvider sourceFileProvider;
94 final OutputProvider outputProvider;
59 95
60 ProviderSourceFileManager(this.sourceFileProvider); 96 ProviderSourceFileManager(this.sourceFileProvider, this.outputProvider);
61 97
62 @override 98 @override
63 SourceFile getSourceFile(uri) { 99 SourceFile getSourceFile(uri) {
64 return sourceFileProvider.getSourceFile(uri); 100 SourceFile sourceFile = sourceFileProvider.getSourceFile(uri);
101 if (sourceFile == null) {
102 sourceFile = outputProvider.getSourceFile(uri);
103 }
104 return sourceFile;
65 } 105 }
66 } 106 }
67 107
68 class RecordingPrintingContext extends LenientPrintingContext { 108 class RecordingPrintingContext extends LenientPrintingContext {
69 CodePositionListener listener; 109 CodePositionListener listener;
110 Map<js.Node, CodePosition> codePositions = <js.Node, CodePosition>{};
70 111
71 RecordingPrintingContext(this.listener); 112 RecordingPrintingContext(this.listener);
72 113
73 @override 114 @override
74 void exitNode(js.Node node, 115 void exitNode(js.Node node,
75 int startPosition, 116 int startPosition,
76 int endPosition, 117 int endPosition,
77 int closingPosition) { 118 int closingPosition) {
119 codePositions[node] =
120 new CodePosition(startPosition, endPosition, closingPosition);
78 listener.onPositions( 121 listener.onPositions(
79 node, startPosition, endPosition, closingPosition); 122 node, startPosition, endPosition, closingPosition);
80 } 123 }
81 } 124 }
82 125
126 /// A [SourceMapper] that records the source locations on each node.
127 class RecordingSourceMapper implements SourceMapper {
128 final SourceMapper sourceMapper;
129 final _LocationRecorder nodeToSourceLocationsMap;
130
131 RecordingSourceMapper(this.sourceMapper, this.nodeToSourceLocationsMap);
132
133 @override
134 void register(js.Node node, int codeOffset, SourceLocation sourceLocation) {
135 nodeToSourceLocationsMap.register(node, codeOffset, sourceLocation);
136 sourceMapper.register(node, codeOffset, sourceLocation);
137 }
138 }
139
140 /// A wrapper of [SourceInformationProcessor] that records source locations and
141 /// code positions.
142 class RecordingSourceInformationProcessor
143 implements SourceInformationProcessor {
144 final RecordingSourceInformationStrategy wrapper;
145 final SourceInformationProcessor processor;
146 final CodePositionRecorder codePositions;
147 final LocationMap nodeToSourceLocationsMap;
148
149 RecordingSourceInformationProcessor(
150 this.wrapper,
151 this.processor,
152 this.codePositions,
153 this.nodeToSourceLocationsMap);
154
155 @override
156 void onPositions(js.Node node,
157 int startPosition,
158 int endPosition,
159 int closingPosition) {
160 codePositions.registerPositions(
161 node, startPosition, endPosition, closingPosition);
162 processor.onPositions(node, startPosition, endPosition, closingPosition);
163 }
164
165 @override
166 void process(js.Node node, BufferedCodeOutput code) {
167 processor.process(node, code);
168 wrapper.registerProcess(
169 node, code, codePositions, nodeToSourceLocationsMap);
170 }
171 }
172
173 /// Information recording for a use of [SourceInformationProcessor].
174 class RecordedSourceInformationProcess {
175 final js.Node root;
176 final String code;
177 final CodePositionRecorder codePositions;
178 final LocationMap nodeToSourceLocationsMap;
179
180 RecordedSourceInformationProcess(
181 this.root,
182 this.code,
183 this.codePositions,
184 this.nodeToSourceLocationsMap);
185 }
186
187
188 /// A wrapper of [JavaScriptSourceInformationStrategy] that records
189 /// [RecordedSourceInformationProcess].
190 class RecordingSourceInformationStrategy
191 extends JavaScriptSourceInformationStrategy {
192 final JavaScriptSourceInformationStrategy strategy;
193 final Map<RecordedSourceInformationProcess, js.Node> processMap =
194 <RecordedSourceInformationProcess, js.Node>{};
195 final Map<js.Node, RecordedSourceInformationProcess> nodeMap =
196 <js.Node, RecordedSourceInformationProcess>{};
197
198 RecordingSourceInformationStrategy(this.strategy);
199
200 @override
201 SourceInformationBuilder createBuilderForContext(AstElement element) {
202 return strategy.createBuilderForContext(element);
203 }
204
205 @override
206 SourceInformationProcessor createProcessor(SourceMapper sourceMapper) {
207 LocationMap nodeToSourceLocationsMap =
208 new _LocationRecorder();
209 CodePositionRecorder codePositions = new CodePositionRecorder();
210 return new RecordingSourceInformationProcessor(
211 this,
212 strategy.createProcessor(new RecordingSourceMapper(
213 sourceMapper, nodeToSourceLocationsMap)),
214 codePositions, nodeToSourceLocationsMap);
215 }
216
217 void registerProcess(js.Node root,
218 BufferedCodeOutput code,
219 CodePositionRecorder codePositions,
220 LocationMap nodeToSourceLocationsMap) {
221 RecordedSourceInformationProcess subProcess =
222 new RecordedSourceInformationProcess(
223 root, code.getText(), codePositions, nodeToSourceLocationsMap);
224 processMap[subProcess] = root;
225 }
226
227 RecordedSourceInformationProcess subProcessForNode(js.Node node) {
228 return nodeMap.putIfAbsent(node, () {
229 for (RecordedSourceInformationProcess subProcess in processMap.keys) {
230 js.Node root = processMap[subProcess];
231 FindVisitor visitor = new FindVisitor(node);
232 root.accept(visitor);
233 if (visitor.found) {
234 return new RecordedSourceInformationProcess(
235 node,
236 subProcess.code,
237 subProcess.codePositions,
238 new _FilteredLocationMap(
239 visitor.nodes, subProcess.nodeToSourceLocationsMap));
240 }
241 return null;
242 }
243 });
244 }
245 }
246
247 /// Visitor that collects all nodes that are within a function. Used by the
248 /// [RecordingSourceInformationStrategy] to filter what is recorded in a
249 /// [RecordedSourceInformationProcess].
250 class FindVisitor extends js.BaseVisitor {
251 final js.Node soughtNode;
252 bool found = false;
253 bool add = false;
254 final Set<js.Node> nodes = new Set<js.Node>();
255
256 FindVisitor(this.soughtNode);
257
258 visitNode(js.Node node) {
259 if (node == soughtNode) {
260 found = true;
261 add = true;
262 }
263 if (add) {
264 nodes.add(node);
265 }
266 node.visitChildren(this);
267 if (node == soughtNode) {
268 add = false;
269 }
270 }
271 }
272
273 const String USE_NEW_SOURCE_INFO = '--use-new-source-info';
274 const String DISABLE_INLINING = '--disable-inlining';
275
83 /// Processor that computes [SourceMapInfo] for the JavaScript compiled for a 276 /// Processor that computes [SourceMapInfo] for the JavaScript compiled for a
84 /// given Dart file. 277 /// given Dart file.
85 class SourceMapProcessor { 278 class SourceMapProcessor {
86 /// If `true` the output from the compilation is written to files. 279 /// If `true` the output from the compilation is written to files.
87 final bool outputToFile; 280 final bool outputToFile;
88 281
89 /// The [Uri] of the Dart entrypoint. 282 /// The [Uri] of the Dart entrypoint.
90 Uri inputUri; 283 Uri inputUri;
91 284
92 /// The name of the JavaScript output file. 285 /// The name of the JavaScript output file.
(...skipping 12 matching lines...) Expand all
105 SourceMapProcessor(String filename, {this.outputToFile: false}) { 298 SourceMapProcessor(String filename, {this.outputToFile: false}) {
106 inputUri = Uri.base.resolve(nativeToUriPath(filename)); 299 inputUri = Uri.base.resolve(nativeToUriPath(filename));
107 jsPath = 'out.js'; 300 jsPath = 'out.js';
108 targetUri = Uri.base.resolve(jsPath); 301 targetUri = Uri.base.resolve(jsPath);
109 sourceMapFileUri = Uri.base.resolve('${jsPath}.map'); 302 sourceMapFileUri = Uri.base.resolve('${jsPath}.map');
110 } 303 }
111 304
112 /// Computes the [SourceMapInfo] for the compiled elements. 305 /// Computes the [SourceMapInfo] for the compiled elements.
113 Future<List<SourceMapInfo>> process( 306 Future<List<SourceMapInfo>> process(
114 List<String> options, 307 List<String> options,
115 {bool verbose: true}) async { 308 {bool verbose: true,
309 bool perElement: true}) async {
116 OutputProvider outputProvider = outputToFile 310 OutputProvider outputProvider = outputToFile
117 ? new OutputProvider() 311 ? new CloningOutputProvider(targetUri, sourceMapFileUri)
118 : new CloningOutputProvider(targetUri, sourceMapFileUri); 312 : new OutputProvider();
119 if (options.contains('--use-new-source-info')) { 313 if (options.contains(USE_NEW_SOURCE_INFO)) {
120 if (verbose) print('Using the new source information system.'); 314 if (verbose) print('Using the new source information system.');
121 useNewSourceInfo = true; 315 useNewSourceInfo = true;
122 } 316 }
123 api.CompilerImpl compiler = await compilerFor( 317 api.CompilerImpl compiler = await compilerFor(
124 outputProvider: outputProvider, 318 outputProvider: outputProvider,
125 // TODO(johnniwinther): Use [verbose] to avoid showing diagnostics. 319 // TODO(johnniwinther): Use [verbose] to avoid showing diagnostics.
126 options: ['--out=$targetUri', '--source-map=$sourceMapFileUri'] 320 options: ['--out=$targetUri', '--source-map=$sourceMapFileUri']
127 ..addAll(options)); 321 ..addAll(options));
128 if (options.contains('--disable-inlining')) { 322 if (options.contains(DISABLE_INLINING)) {
129 if (verbose) print('Inlining disabled'); 323 if (verbose) print('Inlining disabled');
130 compiler.disableInlining = true; 324 compiler.disableInlining = true;
131 } 325 }
132 326
133 JavaScriptBackend backend = compiler.backend; 327 JavaScriptBackend backend = compiler.backend;
134 var handler = compiler.handler; 328 var handler = compiler.handler;
135 SourceFileProvider sourceFileProvider = handler.provider; 329 SourceFileProvider sourceFileProvider = handler.provider;
136 sourceFileManager = new ProviderSourceFileManager(sourceFileProvider); 330 sourceFileManager = new ProviderSourceFileManager(
331 sourceFileProvider,
332 outputProvider);
333 RecordingSourceInformationStrategy strategy =
334 new RecordingSourceInformationStrategy(backend.sourceInformationStrategy );
335 backend.sourceInformationStrategy = strategy;
137 await compiler.run(inputUri); 336 await compiler.run(inputUri);
138 337
139 List<SourceMapInfo> infoList = <SourceMapInfo>[]; 338 List<SourceMapInfo> infoList = <SourceMapInfo>[];
140 backend.generatedCode.forEach((Element element, js.Expression node) { 339 if (perElement) {
141 js.JavaScriptPrintingOptions options = 340 backend.generatedCode.forEach((Element element, js.Expression node) {
142 new js.JavaScriptPrintingOptions(); 341 RecordedSourceInformationProcess subProcess =
143 JavaScriptSourceInformationStrategy sourceInformationStrategy = 342 strategy.subProcessForNode(node);
144 compiler.backend.sourceInformationStrategy; 343 if (subProcess == null) {
145 NodeToSourceLocationsMap nodeMap = new NodeToSourceLocationsMap(); 344 // TODO(johnniwinther): Find out when this is happening and if it
146 SourceInformationProcessor sourceInformationProcessor = 345 // is benign. (Known to happen for `bool#fromString`)
147 sourceInformationStrategy.createProcessor(nodeMap); 346 print('No subProcess found for $element');
148 RecordingPrintingContext printingContext = 347 return;
149 new RecordingPrintingContext(sourceInformationProcessor); 348 }
150 new js.Printer(options, printingContext).visit(node); 349 LocationMap nodeMap = subProcess.nodeToSourceLocationsMap;
151 sourceInformationProcessor.process(node); 350 String code = subProcess.code;
152 351 CodePositionRecorder codePositions = subProcess.codePositions;
153 String code = printingContext.getText(); 352 CodePointComputer visitor =
353 new CodePointComputer(sourceFileManager, code, nodeMap);
354 visitor.apply(node);
355 List<CodePoint> codePoints = visitor.codePoints;
356 infoList.add(new SourceMapInfo(
357 element, code, node,
358 codePoints,
359 codePositions/*strategy.codePositions*/,
360 nodeMap));
361 });
362 } else {
363 // TODO(johnniwinther): Supported multiple output units.
364 RecordedSourceInformationProcess process = strategy.processMap.keys.first;
365 js.Node node = strategy.processMap[process];
366 String code;
367 LocationMap nodeMap;
368 CodePositionRecorder codePositions;
369 nodeMap = process.nodeToSourceLocationsMap;
370 code = process.code;
371 codePositions = process.codePositions;
154 CodePointComputer visitor = 372 CodePointComputer visitor =
155 new CodePointComputer(sourceFileManager, code, nodeMap); 373 new CodePointComputer(sourceFileManager, code, nodeMap);
156 visitor.apply(node); 374 visitor.apply(node);
157 List<CodePoint> codePoints = visitor.codePoints; 375 List<CodePoint> codePoints = visitor.codePoints;
158 infoList.add(new SourceMapInfo(element, code, node, codePoints, nodeMap)); 376 infoList.add(new SourceMapInfo(
159 }); 377 null, code, node,
378 codePoints,
379 codePositions,
380 nodeMap));
381 }
160 382
161 return infoList; 383 return infoList;
162 } 384 }
163 } 385 }
164 386
165 /// Source mapping information for the JavaScript code of an [Element]. 387 /// Source mapping information for the JavaScript code of an [Element].
166 class SourceMapInfo { 388 class SourceMapInfo {
167 final String name; 389 final String name;
168 final Element element; 390 final Element element;
169 final String code; 391 final String code;
170 final js.Expression node; 392 final js.Node node;
171 final List<CodePoint> codePoints; 393 final List<CodePoint> codePoints;
172 final NodeToSourceLocationsMap nodeMap; 394 final CodePositionMap jsCodePositions;
395 final LocationMap nodeMap;
173 396
174 SourceMapInfo( 397 SourceMapInfo(
175 Element element, this.code, this.node, this.codePoints, this.nodeMap) 398 Element element,
176 : this.name = computeElementNameForSourceMaps(element), 399 this.code,
400 this.node,
401 this.codePoints,
402 this.jsCodePositions,
403 this.nodeMap)
404 : this.name =
405 element != null ? computeElementNameForSourceMaps(element) : '',
177 this.element = element; 406 this.element = element;
407
408 String toString() {
409 return '$name:$element';
410 }
178 } 411 }
179 412
180 /// Collection of JavaScript nodes with their source mapped target offsets 413 /// Collection of JavaScript nodes with their source mapped target offsets
181 /// and source locations. 414 /// and source locations.
182 class NodeToSourceLocationsMap implements SourceMapper { 415 abstract class LocationMap {
416 Iterable<js.Node> get nodes;
417
418 Map<int, List<SourceLocation>> operator[] (js.Node node);
419
420 factory LocationMap.recorder() = _LocationRecorder;
421
422 factory LocationMap.filter(Set<js.Node> nodes, LocationMap map) =
423 _FilteredLocationMap;
424
425 }
426
427 class _LocationRecorder
428 implements SourceMapper, LocationMap {
183 final Map<js.Node, Map<int, List<SourceLocation>>> _nodeMap = {}; 429 final Map<js.Node, Map<int, List<SourceLocation>>> _nodeMap = {};
184 430
185 @override 431 @override
186 void register(js.Node node, int codeOffset, SourceLocation sourceLocation) { 432 void register(js.Node node, int codeOffset, SourceLocation sourceLocation) {
187 _nodeMap.putIfAbsent(node, () => {}) 433 _nodeMap.putIfAbsent(node, () => {})
188 .putIfAbsent(codeOffset, () => []) 434 .putIfAbsent(codeOffset, () => [])
189 .add(sourceLocation); 435 .add(sourceLocation);
190 } 436 }
191 437
192 Iterable<js.Node> get nodes => _nodeMap.keys; 438 Iterable<js.Node> get nodes => _nodeMap.keys;
193 439
194 Map<int, List<SourceLocation>> operator[] (js.Node node) { 440 Map<int, List<SourceLocation>> operator[] (js.Node node) {
195 return _nodeMap[node]; 441 return _nodeMap[node];
196 } 442 }
197 } 443 }
198 444
445 class _FilteredLocationMap implements LocationMap {
446 final Set<js.Node> _nodes;
447 final LocationMap map;
448
449 _FilteredLocationMap(this._nodes, this.map);
450
451 Iterable<js.Node> get nodes => map.nodes.where((n) => _nodes.contains(n));
452
453 Map<int, List<SourceLocation>> operator[] (js.Node node) {
454 return map[node];
455 }
456 }
457
458
199 /// Visitor that computes the [CodePoint]s for source mapping locations. 459 /// Visitor that computes the [CodePoint]s for source mapping locations.
200 class CodePointComputer extends js.BaseVisitor { 460 class CodePointComputer extends js.BaseVisitor {
201 final SourceFileManager sourceFileManager; 461 final SourceFileManager sourceFileManager;
202 final String code; 462 final String code;
203 final NodeToSourceLocationsMap nodeMap; 463 final LocationMap nodeMap;
204 List<CodePoint> codePoints = []; 464 List<CodePoint> codePoints = [];
205 465
206 CodePointComputer(this.sourceFileManager, this.code, this.nodeMap); 466 CodePointComputer(this.sourceFileManager, this.code, this.nodeMap);
207 467
208 String nodeToString(js.Node node) { 468 String nodeToString(js.Node node) {
209 js.JavaScriptPrintingOptions options = new js.JavaScriptPrintingOptions( 469 js.JavaScriptPrintingOptions options = new js.JavaScriptPrintingOptions(
210 shouldCompressOutput: true, 470 shouldCompressOutput: true,
211 preferSemicolonToNewlineInMinifiedOutput: true); 471 preferSemicolonToNewlineInMinifiedOutput: true);
212 LenientPrintingContext printingContext = new LenientPrintingContext(); 472 LenientPrintingContext printingContext = new LenientPrintingContext();
213 new js.Printer(options, printingContext).visit(node); 473 new js.Printer(options, printingContext).visit(node);
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 this.jsCode, 589 this.jsCode,
330 this.sourceLocation, 590 this.sourceLocation,
331 this.dartCode, 591 this.dartCode,
332 {this.isMissing: false}); 592 {this.isMissing: false});
333 593
334 String toString() { 594 String toString() {
335 return 'CodePoint[kind=$kind,js=$jsCode,dart=$dartCode,' 595 return 'CodePoint[kind=$kind,js=$jsCode,dart=$dartCode,'
336 'location=$sourceLocation]'; 596 'location=$sourceLocation]';
337 } 597 }
338 } 598 }
OLDNEW
« no previous file with comments | « tests/compiler/dart2js/sourcemaps/js_tracer.dart ('k') | tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698