blob: 91702ab412621dfa77515676f8fc0b17cfd065dd [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library builtin;
import 'dart:io';
// Corelib 'print' implementation.
void _print(arg) {
_Logger._printString(arg.toString());
}
class _Logger {
static void _printString(String s) native "Logger_PrintString";
}
_getPrintClosure() => _print;
void _logResolution(String msg) {
final enabled = false;
if (enabled) {
_Logger._printString(msg);
}
}
// Corelib 'Uri.base' implementation.
Uri _uriBase() {
return new Uri.file(Directory.current.path + "/");
}
_getUriBaseClosure() => _uriBase;
var _httpRequestResponseCode = 0;
var _httpRequestStatusString;
var _httpRequestResponse;
_getHttpRequestResponseCode() => _httpRequestResponseCode;
_getHttpRequestStatusString() => _httpRequestStatusString;
_getHttpRequestResponse() => _httpRequestResponse;
void _requestCompleted(List<int> data, HttpClientResponse response) {
_httpRequestResponseCode = response.statusCode;
_httpRequestStatusString = '${response.statusCode} ${response.reasonPhrase}';
_httpRequestResponse = null;
if (response.statusCode != 200 ||
(response.headers.contentType != null &&
response.headers.contentType.mimeType == 'application/json')) {
return;
}
_httpRequestResponse = data;
}
void _requestFailed(error) {
_httpRequestResponseCode = 0;
_httpRequestStatusString = error.toString();
_httpRequestResponse = null;
}
void _makeHttpRequest(String uri) {
var _client = new HttpClient();
_httpRequestResponseCode = 0;
_httpRequestStatusString = null;
_httpRequestResponse = null;
Uri requestUri = Uri.parse(uri);
_client.getUrl(requestUri)
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
return response
.fold(new BytesBuilder(), (b, d) => b..add(d))
.then((builder) {
_requestCompleted(builder.takeBytes(), response);
});
}).catchError((error) {
_requestFailed(error);
});
}
// Are we running on Windows?
var _isWindows = false;
var _workingWindowsDrivePrefix;
// The current working directory
var _workingDirectoryUri;
// The URI that the entry point script was loaded from. Remembered so that
// package imports can be resolved relative to it.
var _entryPointScript;
// The directory to look in to resolve "package:" scheme URIs.
var _packageRoot;
void _setWindows() {
_isWindows = true;
}
_sanitizeWindowsPath(path) {
// For Windows we need to massage the paths a bit according to
// http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
//
// Convert
// C:\one\two\three
// to
// /C:/one/two/three
if (_isWindows == false) {
// Do nothing when not running Windows.
return path;
}
var fixedPath = "${path.replaceAll('\\', '/')}";
if ((path.length > 2) && (path[1] == ':')) {
// Path begins with a drive letter.
return '/$fixedPath';
}
return fixedPath;
}
_enforceTrailingSlash(uri) {
// Ensure we have a trailing slash character.
if (!uri.endsWith('/')) {
return '$uri/';
}
return uri;
}
_extractDriveLetterPrefix(cwd) {
if (!_isWindows) {
return null;
}
if (cwd.length > 1 && cwd[1] == ':') {
return '/${cwd[0]}:';
}
return null;
}
void _setWorkingDirectory(cwd) {
_workingWindowsDrivePrefix = _extractDriveLetterPrefix(cwd);
cwd = _sanitizeWindowsPath(cwd);
cwd = _enforceTrailingSlash(cwd);
_workingDirectoryUri = new Uri(scheme: 'file', path: cwd);
_logResolution('# Working Directory: $cwd');
}
_setPackageRoot(String packageRoot) {
packageRoot = _enforceTrailingSlash(packageRoot);
_packageRoot = _workingDirectoryUri.resolve(packageRoot);
_logResolution('# Package root: $packageRoot -> $_packageRoot');
}
String _resolveScriptUri(String scriptName) {
if (_workingDirectoryUri == null) {
throw 'No current working directory set.';
}
scriptName = _sanitizeWindowsPath(scriptName);
var scriptUri = Uri.parse(scriptName);
if (scriptUri.scheme != '') {
// Script has a scheme, assume that it is fully formed.
_entryPointScript = scriptUri;
} else {
// Script does not have a scheme, assume that it is a path,
// resolve it against the working directory.
_entryPointScript = _workingDirectoryUri.resolve(scriptName);
}
_logResolution('# Resolved entry point to: $_entryPointScript');
return _entryPointScript.toString();
}
String _resolveUri(String base, String userString) {
var baseUri = Uri.parse(base);
_logResolution('# Resolving: $userString from $base');
var uri = Uri.parse(userString);
var resolved;
if ('dart-ext' == uri.scheme) {
// Relative URIs with scheme dart-ext should be resolved as if with no
// scheme.
resolved = baseUri.resolve(uri.path);
var path = resolved.path;
if (resolved.scheme == 'package') {
// If we are resolving relative to a package URI we go directly to the
// file path and keep the dart-ext scheme. Otherwise, we will lose the
// package URI path part.
path = _filePathFromPackageUri(resolved);
}
resolved = new Uri(scheme: 'dart-ext', path: path);
} else {
resolved = baseUri.resolve(userString);
}
_logResolution('# Resolved to: $resolved');
return resolved.toString();
}
String _filePathFromUri(String userUri) {
var uri = Uri.parse(userUri);
_logResolution('# Getting file path from: $uri');
var path;
switch (uri.scheme) {
case 'file':
path = _filePathFromFileUri(uri);
break;
case 'dart-ext':
path = _filePathFromOtherUri(uri);
break;
case 'package':
path = _filePathFromPackageUri(uri);
break;
case 'http':
path = _filePathFromHttpUri(uri);
break;
default:
// Only handling file and package URIs in standalone binary.
_logResolution('# Unknown scheme (${uri.scheme}) in $uri.');
throw 'Not a known scheme: $uri';
}
if (_isWindows && path.startsWith('/')) {
// For Windows we need to massage the paths a bit according to
// http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
//
// Drop the leading / before the drive letter.
path = path.substring(1);
_logResolution('# Path: Removed leading / -> $path');
}
return path;
}
String _filePathFromFileUri(Uri uri) {
if (!uri.host.isEmpty) {
throw "URIs using the 'file:' scheme may not contain a host.";
}
String path = uri.path;
_logResolution('# Path: $uri -> ${path}');
// Check that the path is not already in the form of /X:.
if (_isWindows && (path.length > 2) && path.startsWith('/') &&
(path[2] != ':')) {
// Absolute path on Windows without a drive letter.
if (_workingWindowsDrivePrefix == null) {
throw 'Could not determine windows drive letter prefix.';
}
_logResolution('# Path: Windows absolute path needs a drive letter.'
' Prepending $_workingWindowsDrivePrefix.');
path = '$_workingWindowsDrivePrefix$path';
}
return path;
}
String _filePathFromOtherUri(Uri uri) {
if (!uri.host.isEmpty) {
throw 'URIs whose paths are used as file paths may not contain a host.';
}
_logResolution('# Path: $uri -> ${uri.path}');
return uri.path;
}
String _filePathFromPackageUri(Uri uri) {
if (!uri.host.isEmpty) {
var path = (uri.path != '') ? '${uri.host}${uri.path}' : uri.host;
var right = 'package:$path';
var wrong = 'package://$path';
throw "URIs using the 'package:' scheme should look like "
"'$right', not '$wrong'.";
}
var packageUri;
var path;
if (_packageRoot != null) {
// Resolve against package root.
packageUri = _packageRoot.resolve(uri.path);
} else {
// Resolve against working directory.
packageUri = _entryPointScript.resolve('packages/${uri.path}');
}
if (packageUri.scheme == 'file') {
path = packageUri.path;
} else {
path = packageUri.toString();
}
_logResolution('# Package: $uri -> $path');
return path;
}
String _filePathFromHttpUri(Uri uri) {
_logResolution('# Path: $uri -> $uri');
return uri.toString();
}