Chromium Code Reviews| Index: lib/src/dartdevc/dartdevc.dart |
| diff --git a/lib/src/dartdevc/dartdevc.dart b/lib/src/dartdevc/dartdevc.dart |
| index fb8834173726ff14a1b34acaec4488d4ca482da8..c6be0acade58743b321f1ec29032cd54e6ca8e97 100644 |
| --- a/lib/src/dartdevc/dartdevc.dart |
| +++ b/lib/src/dartdevc/dartdevc.dart |
| @@ -4,6 +4,7 @@ |
| import 'dart:async'; |
| import 'dart:io'; |
| +import 'dart:convert' show JsonEncoder; |
| import 'package:analyzer/analyzer.dart'; |
| import 'package:barback/barback.dart'; |
| @@ -13,11 +14,42 @@ import 'package:path/path.dart' as p; |
| import '../dart.dart'; |
| import '../io.dart'; |
| +import 'module.dart'; |
| import 'module_reader.dart'; |
| import 'scratch_space.dart'; |
| import 'summaries.dart'; |
| import 'workers.dart'; |
| +// JavaScript snippet to determine the directory a script was run from. |
| +final _currentDirectoryScript = r''' |
| +var _currentDirectory = (function () { |
| + var _url; |
| + var lines = new Error().stack.split('\n'); |
| + function lookupUrl() { |
| + if (lines.length > 2) { |
| + var match = lines[1].match(/^\s+at (.+):\d+:\d+$/); |
| + // Chrome. |
| + if (match) return match[1]; |
| + // Chrome nested eval case. |
| + match = lines[1].match(/^\s+at eval [(](.+):\d+:\d+[)]$/); |
| + if (match) return match[1]; |
| + // Edge. |
| + match = lines[1].match(/^\s+at.+\((.+):\d+:\d+\)$/); |
| + if (match) return match[1]; |
| + // Firefox. |
| + return lines[0].match(/[<][@](.+):\d+:\d+$/)[1]; |
| + } |
| + // Safari. |
| + return lines[0].match(/(.+):\d+:\d+$/)[1]; |
| + } |
| + _url = lookupUrl(); |
| + var lastSlash = _url.lastIndexOf('/'); |
| + if (lastSlash == -1) return _url; |
| + var currentDirectory = _url.substring(0, lastSlash + 1); |
| + return currentDirectory; |
| +})(); |
| +'''; |
| + |
| /// Returns whether or not [dartId] is an app entrypoint (basically, whether or |
| /// not it has a `main` function). |
| Future<bool> isAppEntryPoint( |
| @@ -90,37 +122,85 @@ Map<AssetId, Future<Asset>> bootstrapDartDevcEntrypoint( |
| .join("__") |
| .replaceAll('.', '\$46'); |
| - // Modules not under a `packages` directory need custom module paths. |
| - var customModulePaths = <String>[]; |
| + // Map from module name to module path. |
| + // Modules outside of the `packages` directory have different module path |
| + // and module names. |
| + var modulePaths = new Map<String, String>(); |
| + modulePaths[appModulePath] = appModulePath; |
| + modulePaths['dart_sdk'] = 'dart_sdk'; |
| + |
| var transitiveDeps = await moduleReader.readTransitiveDeps(module); |
| for (var dep in transitiveDeps) { |
| if (dep.dir != 'lib') { |
| var relativePath = p.url.relative(p.url.join(moduleDir, dep.name), |
| from: p.url.dirname(bootstrapId.path)); |
| - customModulePaths.add('"${dep.dir}/${dep.name}": "$relativePath"'); |
| + var jsModuleName = '${dep.dir}/${dep.name}'; |
| + |
| + modulePaths[jsModuleName] = relativePath; |
| } else { |
| var jsModuleName = 'packages/${dep.package}/${dep.name}'; |
| var actualModulePath = p.url.relative( |
| p.url.join(moduleDir, jsModuleName), |
| from: p.url.dirname(bootstrapId.path)); |
| - if (jsModuleName != actualModulePath) { |
| - customModulePaths.add('"$jsModuleName": "$actualModulePath"'); |
| - } |
| + modulePaths[jsModuleName] = actualModulePath; |
| } |
| } |
| var bootstrapContent = ''' |
| +(function() { |
| +$_currentDirectoryScript |
| + |
| +let modulePaths = ${const JsonEncoder.withIndent(' ').convert(modulePaths)}; |
| + |
| +if(!window.\$dartLoader) { |
| + window.\$dartLoader = { |
| + moduleIdToUrl: new Map(), |
| + urlToModuleId: new Map(), |
| + rootDirectories: new Set(), |
| + }; |
| +} |
| + |
| +let customModulePaths = {}; |
| +window.\$dartLoader.rootDirectories.add(_currentDirectory); |
| +for (let moduleName of Object.getOwnPropertyNames(modulePaths)) { |
| + let modulePath = modulePaths[moduleName]; |
| + if (modulePath != moduleName) { |
| + customModulePaths[moduleName] = modulePath; |
| + } |
| + var src = _currentDirectory + modulePath + '.js'; |
| + if (window.\$dartLoader.moduleIdToUrl.has(moduleName)) { |
| + continue; |
| + } |
| + \$dartLoader.moduleIdToUrl.set(moduleName, src); |
| + \$dartLoader.urlToModuleId.set(src, moduleName); |
| +} |
| + |
| require.config({ |
| waitSeconds: 30, |
| - paths: { |
| - ${customModulePaths.join(',\n ')} |
| - } |
| + paths: customModulePaths |
| }); |
| require(["$appModulePath", "dart_sdk"], function(app, dart_sdk) { |
| + // This import is only needed for chrome debugging. We should provide an |
| + // option to compile without it. |
| + dart_sdk._debugger.registerDevtoolsFormatter(); |
| + |
| dart_sdk._isolate_helper.startRootIsolate(() => {}, []); |
| + if (window.\$dartStackTraceUtility && !window.\$dartStackTraceUtility.ready) { |
| + window.\$dartStackTraceUtility.ready = true; |
| + let dart = dart_sdk.dart; |
| + window.\$dartStackTraceUtility.setSourceMapProvider( |
| + function(url) { |
| + var module = window.\$dartLoader.urlToModuleId.get(url); |
| + if (!module) return null; |
| + return dart.getSourceMap(module); |
| + }); |
| + } |
| + window.postMessage({ type: "DDC_STATE_CHANGE", state: "start" }, "*"); |
| + |
| app.$appModuleScope.main(); |
| }); |
| +})(); |
| '''; |
| outputCompleters[bootstrapId] |
| .complete(new Asset.fromString(bootstrapId, bootstrapContent)); |
| @@ -129,6 +209,13 @@ require(["$appModulePath", "dart_sdk"], function(app, dart_sdk) { |
| p.relative(bootstrapId.path, from: p.dirname(dartEntrypointId.path))); |
| var entrypointJsContent = ''' |
| var el = document.createElement("script"); |
| +el = document.createElement("script"); |
|
jakemac
2017/05/19 14:38:06
duplicate code with the line right above :)
Jacob
2017/05/19 16:24:02
Done.
|
| +el.defer = true; |
| +el.async = false; |
| +el.src = "dart_stack_trace_mapper.js"; |
| +document.head.appendChild(el); |
| + |
| +el = document.createElement("script"); |
| el.defer = true; |
| el.async = false; |
| el.src = "require.js"; |
| @@ -191,6 +278,9 @@ Map<AssetId, Future<Asset>> createDartdevcModule( |
| '--library-root=${p.dirname(jsOutputFile.path)}', |
| '--summary-extension=${linkedSummaryExtension.substring(1)}', |
| '--no-summarize', |
| + '--source-map', |
|
jakemac
2017/05/19 14:38:06
We should only include these in DEBUG mode, a few
Jacob
2017/05/19 16:24:02
Done.
|
| + '--source-map-comment', |
| + '--inline-source-map', |
| '-o', |
| jsOutputFile.path, |
| ]); |