mirror of
https://github.com/microsoft/monaco-editor.git
synced 2025-12-22 23:13:02 +01:00
Patch typescriptServices to hard-code ts.sys to undefined (Microsoft/monaco-editor-webpack-plugin#9)
This commit is contained in:
parent
5c1bcb6ae3
commit
c7b54325fd
3 changed files with 12 additions and 1110 deletions
|
|
@ -20,6 +20,12 @@ const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib');
|
||||||
|
|
||||||
var tsServices = fs.readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.js')).toString();
|
var tsServices = fs.readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.js')).toString();
|
||||||
|
|
||||||
|
// Ensure we never run into the node system...
|
||||||
|
// (this also removes require calls that trick webpack into shimming those modules...)
|
||||||
|
tsServices = (
|
||||||
|
tsServices.replace(/\n ts\.sys =([^]*)\n \}\)\(\);/m, `\n // MONACOCHANGE\n ts.sys = undefined;\n // END MONACOCHANGE`)
|
||||||
|
);
|
||||||
|
|
||||||
var tsServices_amd = tsServices +
|
var tsServices_amd = tsServices +
|
||||||
`
|
`
|
||||||
// MONACOCHANGE
|
// MONACOCHANGE
|
||||||
|
|
|
||||||
|
|
@ -4845,561 +4845,9 @@ var ts;
|
||||||
return parseInt(version.substring(1, dot));
|
return parseInt(version.substring(1, dot));
|
||||||
}
|
}
|
||||||
ts.getNodeMajorVersion = getNodeMajorVersion;
|
ts.getNodeMajorVersion = getNodeMajorVersion;
|
||||||
ts.sys = (function () {
|
// MONACOCHANGE
|
||||||
// NodeJS detects "\uFEFF" at the start of the string and *replaces* it with the actual
|
ts.sys = undefined;
|
||||||
// byte order mark from the specified encoding. Using any other byte order mark does
|
// END MONACOCHANGE
|
||||||
// not actually work.
|
|
||||||
var byteOrderMarkIndicator = "\uFEFF";
|
|
||||||
function getNodeSystem() {
|
|
||||||
var _fs = require("fs");
|
|
||||||
var _path = require("path");
|
|
||||||
var _os = require("os");
|
|
||||||
// crypto can be absent on reduced node installations
|
|
||||||
var _crypto;
|
|
||||||
try {
|
|
||||||
_crypto = require("crypto");
|
|
||||||
}
|
|
||||||
catch (_a) {
|
|
||||||
_crypto = undefined;
|
|
||||||
}
|
|
||||||
var nodeVersion = getNodeMajorVersion();
|
|
||||||
var isNode4OrLater = nodeVersion >= 4;
|
|
||||||
var platform = _os.platform();
|
|
||||||
var useCaseSensitiveFileNames = isFileSystemCaseSensitive();
|
|
||||||
var FileSystemEntryKind;
|
|
||||||
(function (FileSystemEntryKind) {
|
|
||||||
FileSystemEntryKind[FileSystemEntryKind["File"] = 0] = "File";
|
|
||||||
FileSystemEntryKind[FileSystemEntryKind["Directory"] = 1] = "Directory";
|
|
||||||
})(FileSystemEntryKind || (FileSystemEntryKind = {}));
|
|
||||||
var useNonPollingWatchers = process.env.TSC_NONPOLLING_WATCHER;
|
|
||||||
var tscWatchFile = process.env.TSC_WATCHFILE;
|
|
||||||
var tscWatchDirectory = process.env.TSC_WATCHDIRECTORY;
|
|
||||||
var dynamicPollingWatchFile;
|
|
||||||
var nodeSystem = {
|
|
||||||
args: process.argv.slice(2),
|
|
||||||
newLine: _os.EOL,
|
|
||||||
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
|
|
||||||
write: function (s) {
|
|
||||||
process.stdout.write(s);
|
|
||||||
},
|
|
||||||
readFile: readFile,
|
|
||||||
writeFile: writeFile,
|
|
||||||
watchFile: getWatchFile(),
|
|
||||||
watchDirectory: getWatchDirectory(),
|
|
||||||
resolvePath: function (path) { return _path.resolve(path); },
|
|
||||||
fileExists: fileExists,
|
|
||||||
directoryExists: directoryExists,
|
|
||||||
createDirectory: function (directoryName) {
|
|
||||||
if (!nodeSystem.directoryExists(directoryName)) {
|
|
||||||
_fs.mkdirSync(directoryName);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getExecutingFilePath: function () {
|
|
||||||
return __filename;
|
|
||||||
},
|
|
||||||
getCurrentDirectory: function () {
|
|
||||||
return process.cwd();
|
|
||||||
},
|
|
||||||
getDirectories: getDirectories,
|
|
||||||
getEnvironmentVariable: function (name) {
|
|
||||||
return process.env[name] || "";
|
|
||||||
},
|
|
||||||
readDirectory: readDirectory,
|
|
||||||
getModifiedTime: getModifiedTime,
|
|
||||||
createHash: _crypto ? createMD5HashUsingNativeCrypto : generateDjb2Hash,
|
|
||||||
getMemoryUsage: function () {
|
|
||||||
if (global.gc) {
|
|
||||||
global.gc();
|
|
||||||
}
|
|
||||||
return process.memoryUsage().heapUsed;
|
|
||||||
},
|
|
||||||
getFileSize: function (path) {
|
|
||||||
try {
|
|
||||||
var stat = _fs.statSync(path);
|
|
||||||
if (stat.isFile()) {
|
|
||||||
return stat.size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch ( /*ignore*/_a) { /*ignore*/ }
|
|
||||||
return 0;
|
|
||||||
},
|
|
||||||
exit: function (exitCode) {
|
|
||||||
process.exit(exitCode);
|
|
||||||
},
|
|
||||||
realpath: function (path) {
|
|
||||||
try {
|
|
||||||
return _fs.realpathSync(path);
|
|
||||||
}
|
|
||||||
catch (_a) {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
debugMode: ts.some(process.execArgv, function (arg) { return /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg); }),
|
|
||||||
tryEnableSourceMapsForHost: function () {
|
|
||||||
try {
|
|
||||||
require("source-map-support").install();
|
|
||||||
}
|
|
||||||
catch (_a) {
|
|
||||||
// Could not enable source maps.
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setTimeout: setTimeout,
|
|
||||||
clearTimeout: clearTimeout,
|
|
||||||
clearScreen: function () {
|
|
||||||
process.stdout.write("\x1Bc");
|
|
||||||
},
|
|
||||||
setBlocking: function () {
|
|
||||||
if (process.stdout && process.stdout._handle && process.stdout._handle.setBlocking) {
|
|
||||||
process.stdout._handle.setBlocking(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return nodeSystem;
|
|
||||||
function isFileSystemCaseSensitive() {
|
|
||||||
// win32\win64 are case insensitive platforms
|
|
||||||
if (platform === "win32" || platform === "win64") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// If this file exists under a different case, we must be case-insensitve.
|
|
||||||
return !fileExists(swapCase(__filename));
|
|
||||||
}
|
|
||||||
/** Convert all lowercase chars to uppercase, and vice-versa */
|
|
||||||
function swapCase(s) {
|
|
||||||
return s.replace(/\w/g, function (ch) {
|
|
||||||
var up = ch.toUpperCase();
|
|
||||||
return ch === up ? ch.toLowerCase() : up;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function getWatchFile() {
|
|
||||||
switch (tscWatchFile) {
|
|
||||||
case "PriorityPollingInterval":
|
|
||||||
// Use polling interval based on priority when create watch using host.watchFile
|
|
||||||
return fsWatchFile;
|
|
||||||
case "DynamicPriorityPolling":
|
|
||||||
// Use polling interval but change the interval depending on file changes and their default polling interval
|
|
||||||
return createDynamicPriorityPollingWatchFile({ getModifiedTime: getModifiedTime, setTimeout: setTimeout });
|
|
||||||
case "UseFsEvents":
|
|
||||||
// Use notifications from FS to watch with falling back to fs.watchFile
|
|
||||||
return watchFileUsingFsWatch;
|
|
||||||
case "UseFsEventsWithFallbackDynamicPolling":
|
|
||||||
// Use notifications from FS to watch with falling back to dynamic watch file
|
|
||||||
dynamicPollingWatchFile = createDynamicPriorityPollingWatchFile({ getModifiedTime: getModifiedTime, setTimeout: setTimeout });
|
|
||||||
return createWatchFileUsingDynamicWatchFile(dynamicPollingWatchFile);
|
|
||||||
case "UseFsEventsOnParentDirectory":
|
|
||||||
// Use notifications from FS to watch with falling back to fs.watchFile
|
|
||||||
return createNonPollingWatchFile();
|
|
||||||
}
|
|
||||||
return useNonPollingWatchers ?
|
|
||||||
createNonPollingWatchFile() :
|
|
||||||
// Default to do not use polling interval as it is before this experiment branch
|
|
||||||
function (fileName, callback) { return fsWatchFile(fileName, callback); };
|
|
||||||
}
|
|
||||||
function getWatchDirectory() {
|
|
||||||
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
|
|
||||||
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
|
|
||||||
var fsSupportsRecursive = isNode4OrLater && (process.platform === "win32" || process.platform === "darwin");
|
|
||||||
if (fsSupportsRecursive) {
|
|
||||||
return watchDirectoryUsingFsWatch;
|
|
||||||
}
|
|
||||||
var watchDirectory = tscWatchDirectory === "RecursiveDirectoryUsingFsWatchFile" ?
|
|
||||||
createWatchDirectoryUsing(fsWatchFile) :
|
|
||||||
tscWatchDirectory === "RecursiveDirectoryUsingDynamicPriorityPolling" ?
|
|
||||||
createWatchDirectoryUsing(dynamicPollingWatchFile || createDynamicPriorityPollingWatchFile({ getModifiedTime: getModifiedTime, setTimeout: setTimeout })) :
|
|
||||||
watchDirectoryUsingFsWatch;
|
|
||||||
var watchDirectoryRecursively = createRecursiveDirectoryWatcher({
|
|
||||||
filePathComparer: useCaseSensitiveFileNames ? ts.compareStringsCaseSensitive : ts.compareStringsCaseInsensitive,
|
|
||||||
directoryExists: directoryExists,
|
|
||||||
getAccessileSortedChildDirectories: function (path) { return getAccessibleFileSystemEntries(path).directories; },
|
|
||||||
watchDirectory: watchDirectory
|
|
||||||
});
|
|
||||||
return function (directoryName, callback, recursive) {
|
|
||||||
if (recursive) {
|
|
||||||
return watchDirectoryRecursively(directoryName, callback);
|
|
||||||
}
|
|
||||||
watchDirectory(directoryName, callback);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function createNonPollingWatchFile() {
|
|
||||||
// One file can have multiple watchers
|
|
||||||
var fileWatcherCallbacks = ts.createMultiMap();
|
|
||||||
var dirWatchers = ts.createMap();
|
|
||||||
var toCanonicalName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames);
|
|
||||||
return nonPollingWatchFile;
|
|
||||||
function nonPollingWatchFile(fileName, callback) {
|
|
||||||
var filePath = toCanonicalName(fileName);
|
|
||||||
fileWatcherCallbacks.add(filePath, callback);
|
|
||||||
var dirPath = ts.getDirectoryPath(filePath) || ".";
|
|
||||||
var watcher = dirWatchers.get(dirPath) || createDirectoryWatcher(ts.getDirectoryPath(fileName) || ".", dirPath);
|
|
||||||
watcher.referenceCount++;
|
|
||||||
return {
|
|
||||||
close: function () {
|
|
||||||
if (watcher.referenceCount === 1) {
|
|
||||||
watcher.close();
|
|
||||||
dirWatchers.delete(dirPath);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
watcher.referenceCount--;
|
|
||||||
}
|
|
||||||
fileWatcherCallbacks.remove(filePath, callback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function createDirectoryWatcher(dirName, dirPath) {
|
|
||||||
var watcher = fsWatchDirectory(dirName, function (_eventName, relativeFileName) {
|
|
||||||
// When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined"
|
|
||||||
var fileName = !ts.isString(relativeFileName)
|
|
||||||
? undefined
|
|
||||||
: ts.getNormalizedAbsolutePath(relativeFileName, dirName);
|
|
||||||
// Some applications save a working file via rename operations
|
|
||||||
var callbacks = fileWatcherCallbacks.get(toCanonicalName(fileName));
|
|
||||||
if (callbacks) {
|
|
||||||
for (var _i = 0, callbacks_1 = callbacks; _i < callbacks_1.length; _i++) {
|
|
||||||
var fileCallback = callbacks_1[_i];
|
|
||||||
fileCallback(fileName, FileWatcherEventKind.Changed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
watcher.referenceCount = 0;
|
|
||||||
dirWatchers.set(dirPath, watcher);
|
|
||||||
return watcher;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function fsWatchFile(fileName, callback, pollingInterval) {
|
|
||||||
_fs.watchFile(fileName, { persistent: true, interval: pollingInterval || 250 }, fileChanged);
|
|
||||||
var eventKind;
|
|
||||||
return {
|
|
||||||
close: function () { return _fs.unwatchFile(fileName, fileChanged); }
|
|
||||||
};
|
|
||||||
function fileChanged(curr, prev) {
|
|
||||||
// previous event kind check is to ensure we recongnize the file as previously also missing when it is restored or renamed twice (that is it disappears and reappears)
|
|
||||||
// In such case, prevTime returned is same as prev time of event when file was deleted as per node documentation
|
|
||||||
var isPreviouslyDeleted = +prev.mtime === 0 || eventKind === FileWatcherEventKind.Deleted;
|
|
||||||
if (+curr.mtime === 0) {
|
|
||||||
if (isPreviouslyDeleted) {
|
|
||||||
// Already deleted file, no need to callback again
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
eventKind = FileWatcherEventKind.Deleted;
|
|
||||||
}
|
|
||||||
else if (isPreviouslyDeleted) {
|
|
||||||
eventKind = FileWatcherEventKind.Created;
|
|
||||||
}
|
|
||||||
// If there is no change in modified time, ignore the event
|
|
||||||
else if (+curr.mtime === +prev.mtime) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// File changed
|
|
||||||
eventKind = FileWatcherEventKind.Changed;
|
|
||||||
}
|
|
||||||
callback(fileName, eventKind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function createFileWatcherCallback(callback) {
|
|
||||||
return function (_fileName, eventKind) { return callback(eventKind === FileWatcherEventKind.Changed ? "change" : "rename", ""); };
|
|
||||||
}
|
|
||||||
function createFsWatchCallbackForFileWatcherCallback(fileName, callback) {
|
|
||||||
return function (eventName) {
|
|
||||||
if (eventName === "rename") {
|
|
||||||
callback(fileName, fileExists(fileName) ? FileWatcherEventKind.Created : FileWatcherEventKind.Deleted);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Change
|
|
||||||
callback(fileName, FileWatcherEventKind.Changed);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback) {
|
|
||||||
return function (eventName, relativeFileName) {
|
|
||||||
// In watchDirectory we only care about adding and removing files (when event name is
|
|
||||||
// "rename"); changes made within files are handled by corresponding fileWatchers (when
|
|
||||||
// event name is "change")
|
|
||||||
if (eventName === "rename") {
|
|
||||||
// When deleting a file, the passed baseFileName is null
|
|
||||||
callback(!relativeFileName ? directoryName : ts.normalizePath(ts.combinePaths(directoryName, relativeFileName)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function fsWatch(fileOrDirectory, entryKind, callback, recursive, fallbackPollingWatchFile, pollingInterval) {
|
|
||||||
var options;
|
|
||||||
/** Watcher for the file system entry depending on whether it is missing or present */
|
|
||||||
var watcher = !fileSystemEntryExists(fileOrDirectory, entryKind) ?
|
|
||||||
watchMissingFileSystemEntry() :
|
|
||||||
watchPresentFileSystemEntry();
|
|
||||||
return {
|
|
||||||
close: function () {
|
|
||||||
// Close the watcher (either existing file system entry watcher or missing file system entry watcher)
|
|
||||||
watcher.close();
|
|
||||||
watcher = undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Invoke the callback with rename and update the watcher if not closed
|
|
||||||
* @param createWatcher
|
|
||||||
*/
|
|
||||||
function invokeCallbackAndUpdateWatcher(createWatcher) {
|
|
||||||
// Call the callback for current directory
|
|
||||||
callback("rename", "");
|
|
||||||
// If watcher is not closed, update it
|
|
||||||
if (watcher) {
|
|
||||||
watcher.close();
|
|
||||||
watcher = createWatcher();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Watch the file or directory that is currently present
|
|
||||||
* and when the watched file or directory is deleted, switch to missing file system entry watcher
|
|
||||||
*/
|
|
||||||
function watchPresentFileSystemEntry() {
|
|
||||||
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
|
|
||||||
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
|
|
||||||
if (options === undefined) {
|
|
||||||
if (isNode4OrLater && (process.platform === "win32" || process.platform === "darwin")) {
|
|
||||||
options = { persistent: true, recursive: !!recursive };
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
options = { persistent: true };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
var presentWatcher = _fs.watch(fileOrDirectory, options, callback);
|
|
||||||
// Watch the missing file or directory or error
|
|
||||||
presentWatcher.on("error", function () { return invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry); });
|
|
||||||
return presentWatcher;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// Catch the exception and use polling instead
|
|
||||||
// Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point
|
|
||||||
// so instead of throwing error, use fs.watchFile
|
|
||||||
return watchPresentFileSystemEntryWithFsWatchFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Watch the file or directory using fs.watchFile since fs.watch threw exception
|
|
||||||
* Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point
|
|
||||||
*/
|
|
||||||
function watchPresentFileSystemEntryWithFsWatchFile() {
|
|
||||||
return fallbackPollingWatchFile(fileOrDirectory, createFileWatcherCallback(callback), pollingInterval);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Watch the file or directory that is missing
|
|
||||||
* and switch to existing file or directory when the missing filesystem entry is created
|
|
||||||
*/
|
|
||||||
function watchMissingFileSystemEntry() {
|
|
||||||
return fallbackPollingWatchFile(fileOrDirectory, function (_fileName, eventKind) {
|
|
||||||
if (eventKind === FileWatcherEventKind.Created && fileSystemEntryExists(fileOrDirectory, entryKind)) {
|
|
||||||
// Call the callback for current file or directory
|
|
||||||
// For now it could be callback for the inner directory creation,
|
|
||||||
// but just return current directory, better than current no-op
|
|
||||||
invokeCallbackAndUpdateWatcher(watchPresentFileSystemEntry);
|
|
||||||
}
|
|
||||||
}, pollingInterval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function watchFileUsingFsWatch(fileName, callback, pollingInterval) {
|
|
||||||
return fsWatch(fileName, 0 /* File */, createFsWatchCallbackForFileWatcherCallback(fileName, callback), /*recursive*/ false, fsWatchFile, pollingInterval);
|
|
||||||
}
|
|
||||||
function createWatchFileUsingDynamicWatchFile(watchFile) {
|
|
||||||
return function (fileName, callback, pollingInterval) { return fsWatch(fileName, 0 /* File */, createFsWatchCallbackForFileWatcherCallback(fileName, callback), /*recursive*/ false, watchFile, pollingInterval); };
|
|
||||||
}
|
|
||||||
function fsWatchDirectory(directoryName, callback, recursive) {
|
|
||||||
return fsWatch(directoryName, 1 /* Directory */, callback, !!recursive, fsWatchFile);
|
|
||||||
}
|
|
||||||
function watchDirectoryUsingFsWatch(directoryName, callback, recursive) {
|
|
||||||
return fsWatchDirectory(directoryName, createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback), recursive);
|
|
||||||
}
|
|
||||||
function createWatchDirectoryUsing(fsWatchFile) {
|
|
||||||
return function (directoryName, callback) { return fsWatchFile(directoryName, function () { return callback(directoryName); }, PollingInterval.Medium); };
|
|
||||||
}
|
|
||||||
function readFile(fileName, _encoding) {
|
|
||||||
if (!fileExists(fileName)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
var buffer = _fs.readFileSync(fileName);
|
|
||||||
var len = buffer.length;
|
|
||||||
if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
|
|
||||||
// Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js,
|
|
||||||
// flip all byte pairs and treat as little endian.
|
|
||||||
len &= ~1; // Round down to a multiple of 2
|
|
||||||
for (var i = 0; i < len; i += 2) {
|
|
||||||
var temp = buffer[i];
|
|
||||||
buffer[i] = buffer[i + 1];
|
|
||||||
buffer[i + 1] = temp;
|
|
||||||
}
|
|
||||||
return buffer.toString("utf16le", 2);
|
|
||||||
}
|
|
||||||
if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) {
|
|
||||||
// Little endian UTF-16 byte order mark detected
|
|
||||||
return buffer.toString("utf16le", 2);
|
|
||||||
}
|
|
||||||
if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) {
|
|
||||||
// UTF-8 byte order mark detected
|
|
||||||
return buffer.toString("utf8", 3);
|
|
||||||
}
|
|
||||||
// Default is UTF-8 with no byte order mark
|
|
||||||
return buffer.toString("utf8");
|
|
||||||
}
|
|
||||||
function writeFile(fileName, data, writeByteOrderMark) {
|
|
||||||
// If a BOM is required, emit one
|
|
||||||
if (writeByteOrderMark) {
|
|
||||||
data = byteOrderMarkIndicator + data;
|
|
||||||
}
|
|
||||||
var fd;
|
|
||||||
try {
|
|
||||||
fd = _fs.openSync(fileName, "w");
|
|
||||||
_fs.writeSync(fd, data, /*position*/ undefined, "utf8");
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (fd !== undefined) {
|
|
||||||
_fs.closeSync(fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function getAccessibleFileSystemEntries(path) {
|
|
||||||
try {
|
|
||||||
var entries = _fs.readdirSync(path || ".").sort();
|
|
||||||
var files = [];
|
|
||||||
var directories = [];
|
|
||||||
for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
|
|
||||||
var entry = entries_1[_i];
|
|
||||||
// This is necessary because on some file system node fails to exclude
|
|
||||||
// "." and "..". See https://github.com/nodejs/node/issues/4002
|
|
||||||
if (entry === "." || entry === "..") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var name = ts.combinePaths(path, entry);
|
|
||||||
var stat = void 0;
|
|
||||||
try {
|
|
||||||
stat = _fs.statSync(name);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (stat.isFile()) {
|
|
||||||
files.push(entry);
|
|
||||||
}
|
|
||||||
else if (stat.isDirectory()) {
|
|
||||||
directories.push(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { files: files, directories: directories };
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return ts.emptyFileSystemEntries;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function readDirectory(path, extensions, excludes, includes, depth) {
|
|
||||||
return ts.matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries);
|
|
||||||
}
|
|
||||||
function fileSystemEntryExists(path, entryKind) {
|
|
||||||
try {
|
|
||||||
var stat = _fs.statSync(path);
|
|
||||||
switch (entryKind) {
|
|
||||||
case 0 /* File */: return stat.isFile();
|
|
||||||
case 1 /* Directory */: return stat.isDirectory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function fileExists(path) {
|
|
||||||
return fileSystemEntryExists(path, 0 /* File */);
|
|
||||||
}
|
|
||||||
function directoryExists(path) {
|
|
||||||
return fileSystemEntryExists(path, 1 /* Directory */);
|
|
||||||
}
|
|
||||||
function getDirectories(path) {
|
|
||||||
return ts.filter(_fs.readdirSync(path), function (dir) { return fileSystemEntryExists(ts.combinePaths(path, dir), 1 /* Directory */); });
|
|
||||||
}
|
|
||||||
function getModifiedTime(path) {
|
|
||||||
try {
|
|
||||||
return _fs.statSync(path).mtime;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* djb2 hashing algorithm
|
|
||||||
* http://www.cse.yorku.ca/~oz/hash.html
|
|
||||||
*/
|
|
||||||
function generateDjb2Hash(data) {
|
|
||||||
var chars = data.split("").map(function (str) { return str.charCodeAt(0); });
|
|
||||||
return "" + chars.reduce(function (prev, curr) { return ((prev << 5) + prev) + curr; }, 5381);
|
|
||||||
}
|
|
||||||
function createMD5HashUsingNativeCrypto(data) {
|
|
||||||
var hash = _crypto.createHash("md5");
|
|
||||||
hash.update(data);
|
|
||||||
return hash.digest("hex");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function getChakraSystem() {
|
|
||||||
var realpath = ChakraHost.realpath && (function (path) { return ChakraHost.realpath(path); });
|
|
||||||
return {
|
|
||||||
newLine: ChakraHost.newLine || "\r\n",
|
|
||||||
args: ChakraHost.args,
|
|
||||||
useCaseSensitiveFileNames: !!ChakraHost.useCaseSensitiveFileNames,
|
|
||||||
write: ChakraHost.echo,
|
|
||||||
readFile: function (path, _encoding) {
|
|
||||||
// encoding is automatically handled by the implementation in ChakraHost
|
|
||||||
return ChakraHost.readFile(path);
|
|
||||||
},
|
|
||||||
writeFile: function (path, data, writeByteOrderMark) {
|
|
||||||
// If a BOM is required, emit one
|
|
||||||
if (writeByteOrderMark) {
|
|
||||||
data = byteOrderMarkIndicator + data;
|
|
||||||
}
|
|
||||||
ChakraHost.writeFile(path, data);
|
|
||||||
},
|
|
||||||
resolvePath: ChakraHost.resolvePath,
|
|
||||||
fileExists: ChakraHost.fileExists,
|
|
||||||
directoryExists: ChakraHost.directoryExists,
|
|
||||||
createDirectory: ChakraHost.createDirectory,
|
|
||||||
getExecutingFilePath: function () { return ChakraHost.executingFile; },
|
|
||||||
getCurrentDirectory: function () { return ChakraHost.currentDirectory; },
|
|
||||||
getDirectories: ChakraHost.getDirectories,
|
|
||||||
getEnvironmentVariable: ChakraHost.getEnvironmentVariable || (function () { return ""; }),
|
|
||||||
readDirectory: function (path, extensions, excludes, includes, _depth) {
|
|
||||||
var pattern = ts.getFileMatcherPatterns(path, excludes, includes, !!ChakraHost.useCaseSensitiveFileNames, ChakraHost.currentDirectory);
|
|
||||||
return ChakraHost.readDirectory(path, extensions, pattern.basePaths, pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern);
|
|
||||||
},
|
|
||||||
exit: ChakraHost.quit,
|
|
||||||
realpath: realpath
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function recursiveCreateDirectory(directoryPath, sys) {
|
|
||||||
var basePath = ts.getDirectoryPath(directoryPath);
|
|
||||||
var shouldCreateParent = basePath !== "" && directoryPath !== basePath && !sys.directoryExists(basePath);
|
|
||||||
if (shouldCreateParent) {
|
|
||||||
recursiveCreateDirectory(basePath, sys);
|
|
||||||
}
|
|
||||||
if (shouldCreateParent || !sys.directoryExists(directoryPath)) {
|
|
||||||
sys.createDirectory(directoryPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var sys;
|
|
||||||
if (typeof ChakraHost !== "undefined") {
|
|
||||||
sys = getChakraSystem();
|
|
||||||
}
|
|
||||||
else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") {
|
|
||||||
// process and process.nextTick checks if current environment is node-like
|
|
||||||
// process.browser check excludes webpack and browserify
|
|
||||||
sys = getNodeSystem();
|
|
||||||
}
|
|
||||||
if (sys) {
|
|
||||||
// patch writefile to create folder before writing the file
|
|
||||||
var originalWriteFile_1 = sys.writeFile;
|
|
||||||
sys.writeFile = function (path, data, writeBom) {
|
|
||||||
var directoryPath = ts.getDirectoryPath(ts.normalizeSlashes(path));
|
|
||||||
if (directoryPath && !sys.directoryExists(directoryPath)) {
|
|
||||||
recursiveCreateDirectory(directoryPath, sys);
|
|
||||||
}
|
|
||||||
originalWriteFile_1.call(sys, path, data, writeBom);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return sys;
|
|
||||||
})();
|
|
||||||
if (ts.sys && ts.sys.getEnvironmentVariable) {
|
if (ts.sys && ts.sys.getEnvironmentVariable) {
|
||||||
setCustomPollingValues(ts.sys);
|
setCustomPollingValues(ts.sys);
|
||||||
ts.Debug.currentAssertionLevel = /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))
|
ts.Debug.currentAssertionLevel = /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))
|
||||||
|
|
|
||||||
|
|
@ -4845,561 +4845,9 @@ var ts;
|
||||||
return parseInt(version.substring(1, dot));
|
return parseInt(version.substring(1, dot));
|
||||||
}
|
}
|
||||||
ts.getNodeMajorVersion = getNodeMajorVersion;
|
ts.getNodeMajorVersion = getNodeMajorVersion;
|
||||||
ts.sys = (function () {
|
// MONACOCHANGE
|
||||||
// NodeJS detects "\uFEFF" at the start of the string and *replaces* it with the actual
|
ts.sys = undefined;
|
||||||
// byte order mark from the specified encoding. Using any other byte order mark does
|
// END MONACOCHANGE
|
||||||
// not actually work.
|
|
||||||
var byteOrderMarkIndicator = "\uFEFF";
|
|
||||||
function getNodeSystem() {
|
|
||||||
var _fs = require("fs");
|
|
||||||
var _path = require("path");
|
|
||||||
var _os = require("os");
|
|
||||||
// crypto can be absent on reduced node installations
|
|
||||||
var _crypto;
|
|
||||||
try {
|
|
||||||
_crypto = require("crypto");
|
|
||||||
}
|
|
||||||
catch (_a) {
|
|
||||||
_crypto = undefined;
|
|
||||||
}
|
|
||||||
var nodeVersion = getNodeMajorVersion();
|
|
||||||
var isNode4OrLater = nodeVersion >= 4;
|
|
||||||
var platform = _os.platform();
|
|
||||||
var useCaseSensitiveFileNames = isFileSystemCaseSensitive();
|
|
||||||
var FileSystemEntryKind;
|
|
||||||
(function (FileSystemEntryKind) {
|
|
||||||
FileSystemEntryKind[FileSystemEntryKind["File"] = 0] = "File";
|
|
||||||
FileSystemEntryKind[FileSystemEntryKind["Directory"] = 1] = "Directory";
|
|
||||||
})(FileSystemEntryKind || (FileSystemEntryKind = {}));
|
|
||||||
var useNonPollingWatchers = process.env.TSC_NONPOLLING_WATCHER;
|
|
||||||
var tscWatchFile = process.env.TSC_WATCHFILE;
|
|
||||||
var tscWatchDirectory = process.env.TSC_WATCHDIRECTORY;
|
|
||||||
var dynamicPollingWatchFile;
|
|
||||||
var nodeSystem = {
|
|
||||||
args: process.argv.slice(2),
|
|
||||||
newLine: _os.EOL,
|
|
||||||
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
|
|
||||||
write: function (s) {
|
|
||||||
process.stdout.write(s);
|
|
||||||
},
|
|
||||||
readFile: readFile,
|
|
||||||
writeFile: writeFile,
|
|
||||||
watchFile: getWatchFile(),
|
|
||||||
watchDirectory: getWatchDirectory(),
|
|
||||||
resolvePath: function (path) { return _path.resolve(path); },
|
|
||||||
fileExists: fileExists,
|
|
||||||
directoryExists: directoryExists,
|
|
||||||
createDirectory: function (directoryName) {
|
|
||||||
if (!nodeSystem.directoryExists(directoryName)) {
|
|
||||||
_fs.mkdirSync(directoryName);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getExecutingFilePath: function () {
|
|
||||||
return __filename;
|
|
||||||
},
|
|
||||||
getCurrentDirectory: function () {
|
|
||||||
return process.cwd();
|
|
||||||
},
|
|
||||||
getDirectories: getDirectories,
|
|
||||||
getEnvironmentVariable: function (name) {
|
|
||||||
return process.env[name] || "";
|
|
||||||
},
|
|
||||||
readDirectory: readDirectory,
|
|
||||||
getModifiedTime: getModifiedTime,
|
|
||||||
createHash: _crypto ? createMD5HashUsingNativeCrypto : generateDjb2Hash,
|
|
||||||
getMemoryUsage: function () {
|
|
||||||
if (global.gc) {
|
|
||||||
global.gc();
|
|
||||||
}
|
|
||||||
return process.memoryUsage().heapUsed;
|
|
||||||
},
|
|
||||||
getFileSize: function (path) {
|
|
||||||
try {
|
|
||||||
var stat = _fs.statSync(path);
|
|
||||||
if (stat.isFile()) {
|
|
||||||
return stat.size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch ( /*ignore*/_a) { /*ignore*/ }
|
|
||||||
return 0;
|
|
||||||
},
|
|
||||||
exit: function (exitCode) {
|
|
||||||
process.exit(exitCode);
|
|
||||||
},
|
|
||||||
realpath: function (path) {
|
|
||||||
try {
|
|
||||||
return _fs.realpathSync(path);
|
|
||||||
}
|
|
||||||
catch (_a) {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
debugMode: ts.some(process.execArgv, function (arg) { return /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg); }),
|
|
||||||
tryEnableSourceMapsForHost: function () {
|
|
||||||
try {
|
|
||||||
require("source-map-support").install();
|
|
||||||
}
|
|
||||||
catch (_a) {
|
|
||||||
// Could not enable source maps.
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setTimeout: setTimeout,
|
|
||||||
clearTimeout: clearTimeout,
|
|
||||||
clearScreen: function () {
|
|
||||||
process.stdout.write("\x1Bc");
|
|
||||||
},
|
|
||||||
setBlocking: function () {
|
|
||||||
if (process.stdout && process.stdout._handle && process.stdout._handle.setBlocking) {
|
|
||||||
process.stdout._handle.setBlocking(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return nodeSystem;
|
|
||||||
function isFileSystemCaseSensitive() {
|
|
||||||
// win32\win64 are case insensitive platforms
|
|
||||||
if (platform === "win32" || platform === "win64") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// If this file exists under a different case, we must be case-insensitve.
|
|
||||||
return !fileExists(swapCase(__filename));
|
|
||||||
}
|
|
||||||
/** Convert all lowercase chars to uppercase, and vice-versa */
|
|
||||||
function swapCase(s) {
|
|
||||||
return s.replace(/\w/g, function (ch) {
|
|
||||||
var up = ch.toUpperCase();
|
|
||||||
return ch === up ? ch.toLowerCase() : up;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function getWatchFile() {
|
|
||||||
switch (tscWatchFile) {
|
|
||||||
case "PriorityPollingInterval":
|
|
||||||
// Use polling interval based on priority when create watch using host.watchFile
|
|
||||||
return fsWatchFile;
|
|
||||||
case "DynamicPriorityPolling":
|
|
||||||
// Use polling interval but change the interval depending on file changes and their default polling interval
|
|
||||||
return createDynamicPriorityPollingWatchFile({ getModifiedTime: getModifiedTime, setTimeout: setTimeout });
|
|
||||||
case "UseFsEvents":
|
|
||||||
// Use notifications from FS to watch with falling back to fs.watchFile
|
|
||||||
return watchFileUsingFsWatch;
|
|
||||||
case "UseFsEventsWithFallbackDynamicPolling":
|
|
||||||
// Use notifications from FS to watch with falling back to dynamic watch file
|
|
||||||
dynamicPollingWatchFile = createDynamicPriorityPollingWatchFile({ getModifiedTime: getModifiedTime, setTimeout: setTimeout });
|
|
||||||
return createWatchFileUsingDynamicWatchFile(dynamicPollingWatchFile);
|
|
||||||
case "UseFsEventsOnParentDirectory":
|
|
||||||
// Use notifications from FS to watch with falling back to fs.watchFile
|
|
||||||
return createNonPollingWatchFile();
|
|
||||||
}
|
|
||||||
return useNonPollingWatchers ?
|
|
||||||
createNonPollingWatchFile() :
|
|
||||||
// Default to do not use polling interval as it is before this experiment branch
|
|
||||||
function (fileName, callback) { return fsWatchFile(fileName, callback); };
|
|
||||||
}
|
|
||||||
function getWatchDirectory() {
|
|
||||||
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
|
|
||||||
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
|
|
||||||
var fsSupportsRecursive = isNode4OrLater && (process.platform === "win32" || process.platform === "darwin");
|
|
||||||
if (fsSupportsRecursive) {
|
|
||||||
return watchDirectoryUsingFsWatch;
|
|
||||||
}
|
|
||||||
var watchDirectory = tscWatchDirectory === "RecursiveDirectoryUsingFsWatchFile" ?
|
|
||||||
createWatchDirectoryUsing(fsWatchFile) :
|
|
||||||
tscWatchDirectory === "RecursiveDirectoryUsingDynamicPriorityPolling" ?
|
|
||||||
createWatchDirectoryUsing(dynamicPollingWatchFile || createDynamicPriorityPollingWatchFile({ getModifiedTime: getModifiedTime, setTimeout: setTimeout })) :
|
|
||||||
watchDirectoryUsingFsWatch;
|
|
||||||
var watchDirectoryRecursively = createRecursiveDirectoryWatcher({
|
|
||||||
filePathComparer: useCaseSensitiveFileNames ? ts.compareStringsCaseSensitive : ts.compareStringsCaseInsensitive,
|
|
||||||
directoryExists: directoryExists,
|
|
||||||
getAccessileSortedChildDirectories: function (path) { return getAccessibleFileSystemEntries(path).directories; },
|
|
||||||
watchDirectory: watchDirectory
|
|
||||||
});
|
|
||||||
return function (directoryName, callback, recursive) {
|
|
||||||
if (recursive) {
|
|
||||||
return watchDirectoryRecursively(directoryName, callback);
|
|
||||||
}
|
|
||||||
watchDirectory(directoryName, callback);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function createNonPollingWatchFile() {
|
|
||||||
// One file can have multiple watchers
|
|
||||||
var fileWatcherCallbacks = ts.createMultiMap();
|
|
||||||
var dirWatchers = ts.createMap();
|
|
||||||
var toCanonicalName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames);
|
|
||||||
return nonPollingWatchFile;
|
|
||||||
function nonPollingWatchFile(fileName, callback) {
|
|
||||||
var filePath = toCanonicalName(fileName);
|
|
||||||
fileWatcherCallbacks.add(filePath, callback);
|
|
||||||
var dirPath = ts.getDirectoryPath(filePath) || ".";
|
|
||||||
var watcher = dirWatchers.get(dirPath) || createDirectoryWatcher(ts.getDirectoryPath(fileName) || ".", dirPath);
|
|
||||||
watcher.referenceCount++;
|
|
||||||
return {
|
|
||||||
close: function () {
|
|
||||||
if (watcher.referenceCount === 1) {
|
|
||||||
watcher.close();
|
|
||||||
dirWatchers.delete(dirPath);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
watcher.referenceCount--;
|
|
||||||
}
|
|
||||||
fileWatcherCallbacks.remove(filePath, callback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function createDirectoryWatcher(dirName, dirPath) {
|
|
||||||
var watcher = fsWatchDirectory(dirName, function (_eventName, relativeFileName) {
|
|
||||||
// When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined"
|
|
||||||
var fileName = !ts.isString(relativeFileName)
|
|
||||||
? undefined
|
|
||||||
: ts.getNormalizedAbsolutePath(relativeFileName, dirName);
|
|
||||||
// Some applications save a working file via rename operations
|
|
||||||
var callbacks = fileWatcherCallbacks.get(toCanonicalName(fileName));
|
|
||||||
if (callbacks) {
|
|
||||||
for (var _i = 0, callbacks_1 = callbacks; _i < callbacks_1.length; _i++) {
|
|
||||||
var fileCallback = callbacks_1[_i];
|
|
||||||
fileCallback(fileName, FileWatcherEventKind.Changed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
watcher.referenceCount = 0;
|
|
||||||
dirWatchers.set(dirPath, watcher);
|
|
||||||
return watcher;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function fsWatchFile(fileName, callback, pollingInterval) {
|
|
||||||
_fs.watchFile(fileName, { persistent: true, interval: pollingInterval || 250 }, fileChanged);
|
|
||||||
var eventKind;
|
|
||||||
return {
|
|
||||||
close: function () { return _fs.unwatchFile(fileName, fileChanged); }
|
|
||||||
};
|
|
||||||
function fileChanged(curr, prev) {
|
|
||||||
// previous event kind check is to ensure we recongnize the file as previously also missing when it is restored or renamed twice (that is it disappears and reappears)
|
|
||||||
// In such case, prevTime returned is same as prev time of event when file was deleted as per node documentation
|
|
||||||
var isPreviouslyDeleted = +prev.mtime === 0 || eventKind === FileWatcherEventKind.Deleted;
|
|
||||||
if (+curr.mtime === 0) {
|
|
||||||
if (isPreviouslyDeleted) {
|
|
||||||
// Already deleted file, no need to callback again
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
eventKind = FileWatcherEventKind.Deleted;
|
|
||||||
}
|
|
||||||
else if (isPreviouslyDeleted) {
|
|
||||||
eventKind = FileWatcherEventKind.Created;
|
|
||||||
}
|
|
||||||
// If there is no change in modified time, ignore the event
|
|
||||||
else if (+curr.mtime === +prev.mtime) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// File changed
|
|
||||||
eventKind = FileWatcherEventKind.Changed;
|
|
||||||
}
|
|
||||||
callback(fileName, eventKind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function createFileWatcherCallback(callback) {
|
|
||||||
return function (_fileName, eventKind) { return callback(eventKind === FileWatcherEventKind.Changed ? "change" : "rename", ""); };
|
|
||||||
}
|
|
||||||
function createFsWatchCallbackForFileWatcherCallback(fileName, callback) {
|
|
||||||
return function (eventName) {
|
|
||||||
if (eventName === "rename") {
|
|
||||||
callback(fileName, fileExists(fileName) ? FileWatcherEventKind.Created : FileWatcherEventKind.Deleted);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Change
|
|
||||||
callback(fileName, FileWatcherEventKind.Changed);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback) {
|
|
||||||
return function (eventName, relativeFileName) {
|
|
||||||
// In watchDirectory we only care about adding and removing files (when event name is
|
|
||||||
// "rename"); changes made within files are handled by corresponding fileWatchers (when
|
|
||||||
// event name is "change")
|
|
||||||
if (eventName === "rename") {
|
|
||||||
// When deleting a file, the passed baseFileName is null
|
|
||||||
callback(!relativeFileName ? directoryName : ts.normalizePath(ts.combinePaths(directoryName, relativeFileName)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function fsWatch(fileOrDirectory, entryKind, callback, recursive, fallbackPollingWatchFile, pollingInterval) {
|
|
||||||
var options;
|
|
||||||
/** Watcher for the file system entry depending on whether it is missing or present */
|
|
||||||
var watcher = !fileSystemEntryExists(fileOrDirectory, entryKind) ?
|
|
||||||
watchMissingFileSystemEntry() :
|
|
||||||
watchPresentFileSystemEntry();
|
|
||||||
return {
|
|
||||||
close: function () {
|
|
||||||
// Close the watcher (either existing file system entry watcher or missing file system entry watcher)
|
|
||||||
watcher.close();
|
|
||||||
watcher = undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Invoke the callback with rename and update the watcher if not closed
|
|
||||||
* @param createWatcher
|
|
||||||
*/
|
|
||||||
function invokeCallbackAndUpdateWatcher(createWatcher) {
|
|
||||||
// Call the callback for current directory
|
|
||||||
callback("rename", "");
|
|
||||||
// If watcher is not closed, update it
|
|
||||||
if (watcher) {
|
|
||||||
watcher.close();
|
|
||||||
watcher = createWatcher();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Watch the file or directory that is currently present
|
|
||||||
* and when the watched file or directory is deleted, switch to missing file system entry watcher
|
|
||||||
*/
|
|
||||||
function watchPresentFileSystemEntry() {
|
|
||||||
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
|
|
||||||
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
|
|
||||||
if (options === undefined) {
|
|
||||||
if (isNode4OrLater && (process.platform === "win32" || process.platform === "darwin")) {
|
|
||||||
options = { persistent: true, recursive: !!recursive };
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
options = { persistent: true };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
var presentWatcher = _fs.watch(fileOrDirectory, options, callback);
|
|
||||||
// Watch the missing file or directory or error
|
|
||||||
presentWatcher.on("error", function () { return invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry); });
|
|
||||||
return presentWatcher;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// Catch the exception and use polling instead
|
|
||||||
// Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point
|
|
||||||
// so instead of throwing error, use fs.watchFile
|
|
||||||
return watchPresentFileSystemEntryWithFsWatchFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Watch the file or directory using fs.watchFile since fs.watch threw exception
|
|
||||||
* Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point
|
|
||||||
*/
|
|
||||||
function watchPresentFileSystemEntryWithFsWatchFile() {
|
|
||||||
return fallbackPollingWatchFile(fileOrDirectory, createFileWatcherCallback(callback), pollingInterval);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Watch the file or directory that is missing
|
|
||||||
* and switch to existing file or directory when the missing filesystem entry is created
|
|
||||||
*/
|
|
||||||
function watchMissingFileSystemEntry() {
|
|
||||||
return fallbackPollingWatchFile(fileOrDirectory, function (_fileName, eventKind) {
|
|
||||||
if (eventKind === FileWatcherEventKind.Created && fileSystemEntryExists(fileOrDirectory, entryKind)) {
|
|
||||||
// Call the callback for current file or directory
|
|
||||||
// For now it could be callback for the inner directory creation,
|
|
||||||
// but just return current directory, better than current no-op
|
|
||||||
invokeCallbackAndUpdateWatcher(watchPresentFileSystemEntry);
|
|
||||||
}
|
|
||||||
}, pollingInterval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function watchFileUsingFsWatch(fileName, callback, pollingInterval) {
|
|
||||||
return fsWatch(fileName, 0 /* File */, createFsWatchCallbackForFileWatcherCallback(fileName, callback), /*recursive*/ false, fsWatchFile, pollingInterval);
|
|
||||||
}
|
|
||||||
function createWatchFileUsingDynamicWatchFile(watchFile) {
|
|
||||||
return function (fileName, callback, pollingInterval) { return fsWatch(fileName, 0 /* File */, createFsWatchCallbackForFileWatcherCallback(fileName, callback), /*recursive*/ false, watchFile, pollingInterval); };
|
|
||||||
}
|
|
||||||
function fsWatchDirectory(directoryName, callback, recursive) {
|
|
||||||
return fsWatch(directoryName, 1 /* Directory */, callback, !!recursive, fsWatchFile);
|
|
||||||
}
|
|
||||||
function watchDirectoryUsingFsWatch(directoryName, callback, recursive) {
|
|
||||||
return fsWatchDirectory(directoryName, createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback), recursive);
|
|
||||||
}
|
|
||||||
function createWatchDirectoryUsing(fsWatchFile) {
|
|
||||||
return function (directoryName, callback) { return fsWatchFile(directoryName, function () { return callback(directoryName); }, PollingInterval.Medium); };
|
|
||||||
}
|
|
||||||
function readFile(fileName, _encoding) {
|
|
||||||
if (!fileExists(fileName)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
var buffer = _fs.readFileSync(fileName);
|
|
||||||
var len = buffer.length;
|
|
||||||
if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
|
|
||||||
// Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js,
|
|
||||||
// flip all byte pairs and treat as little endian.
|
|
||||||
len &= ~1; // Round down to a multiple of 2
|
|
||||||
for (var i = 0; i < len; i += 2) {
|
|
||||||
var temp = buffer[i];
|
|
||||||
buffer[i] = buffer[i + 1];
|
|
||||||
buffer[i + 1] = temp;
|
|
||||||
}
|
|
||||||
return buffer.toString("utf16le", 2);
|
|
||||||
}
|
|
||||||
if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) {
|
|
||||||
// Little endian UTF-16 byte order mark detected
|
|
||||||
return buffer.toString("utf16le", 2);
|
|
||||||
}
|
|
||||||
if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) {
|
|
||||||
// UTF-8 byte order mark detected
|
|
||||||
return buffer.toString("utf8", 3);
|
|
||||||
}
|
|
||||||
// Default is UTF-8 with no byte order mark
|
|
||||||
return buffer.toString("utf8");
|
|
||||||
}
|
|
||||||
function writeFile(fileName, data, writeByteOrderMark) {
|
|
||||||
// If a BOM is required, emit one
|
|
||||||
if (writeByteOrderMark) {
|
|
||||||
data = byteOrderMarkIndicator + data;
|
|
||||||
}
|
|
||||||
var fd;
|
|
||||||
try {
|
|
||||||
fd = _fs.openSync(fileName, "w");
|
|
||||||
_fs.writeSync(fd, data, /*position*/ undefined, "utf8");
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (fd !== undefined) {
|
|
||||||
_fs.closeSync(fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function getAccessibleFileSystemEntries(path) {
|
|
||||||
try {
|
|
||||||
var entries = _fs.readdirSync(path || ".").sort();
|
|
||||||
var files = [];
|
|
||||||
var directories = [];
|
|
||||||
for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
|
|
||||||
var entry = entries_1[_i];
|
|
||||||
// This is necessary because on some file system node fails to exclude
|
|
||||||
// "." and "..". See https://github.com/nodejs/node/issues/4002
|
|
||||||
if (entry === "." || entry === "..") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var name = ts.combinePaths(path, entry);
|
|
||||||
var stat = void 0;
|
|
||||||
try {
|
|
||||||
stat = _fs.statSync(name);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (stat.isFile()) {
|
|
||||||
files.push(entry);
|
|
||||||
}
|
|
||||||
else if (stat.isDirectory()) {
|
|
||||||
directories.push(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { files: files, directories: directories };
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return ts.emptyFileSystemEntries;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function readDirectory(path, extensions, excludes, includes, depth) {
|
|
||||||
return ts.matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries);
|
|
||||||
}
|
|
||||||
function fileSystemEntryExists(path, entryKind) {
|
|
||||||
try {
|
|
||||||
var stat = _fs.statSync(path);
|
|
||||||
switch (entryKind) {
|
|
||||||
case 0 /* File */: return stat.isFile();
|
|
||||||
case 1 /* Directory */: return stat.isDirectory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function fileExists(path) {
|
|
||||||
return fileSystemEntryExists(path, 0 /* File */);
|
|
||||||
}
|
|
||||||
function directoryExists(path) {
|
|
||||||
return fileSystemEntryExists(path, 1 /* Directory */);
|
|
||||||
}
|
|
||||||
function getDirectories(path) {
|
|
||||||
return ts.filter(_fs.readdirSync(path), function (dir) { return fileSystemEntryExists(ts.combinePaths(path, dir), 1 /* Directory */); });
|
|
||||||
}
|
|
||||||
function getModifiedTime(path) {
|
|
||||||
try {
|
|
||||||
return _fs.statSync(path).mtime;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* djb2 hashing algorithm
|
|
||||||
* http://www.cse.yorku.ca/~oz/hash.html
|
|
||||||
*/
|
|
||||||
function generateDjb2Hash(data) {
|
|
||||||
var chars = data.split("").map(function (str) { return str.charCodeAt(0); });
|
|
||||||
return "" + chars.reduce(function (prev, curr) { return ((prev << 5) + prev) + curr; }, 5381);
|
|
||||||
}
|
|
||||||
function createMD5HashUsingNativeCrypto(data) {
|
|
||||||
var hash = _crypto.createHash("md5");
|
|
||||||
hash.update(data);
|
|
||||||
return hash.digest("hex");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function getChakraSystem() {
|
|
||||||
var realpath = ChakraHost.realpath && (function (path) { return ChakraHost.realpath(path); });
|
|
||||||
return {
|
|
||||||
newLine: ChakraHost.newLine || "\r\n",
|
|
||||||
args: ChakraHost.args,
|
|
||||||
useCaseSensitiveFileNames: !!ChakraHost.useCaseSensitiveFileNames,
|
|
||||||
write: ChakraHost.echo,
|
|
||||||
readFile: function (path, _encoding) {
|
|
||||||
// encoding is automatically handled by the implementation in ChakraHost
|
|
||||||
return ChakraHost.readFile(path);
|
|
||||||
},
|
|
||||||
writeFile: function (path, data, writeByteOrderMark) {
|
|
||||||
// If a BOM is required, emit one
|
|
||||||
if (writeByteOrderMark) {
|
|
||||||
data = byteOrderMarkIndicator + data;
|
|
||||||
}
|
|
||||||
ChakraHost.writeFile(path, data);
|
|
||||||
},
|
|
||||||
resolvePath: ChakraHost.resolvePath,
|
|
||||||
fileExists: ChakraHost.fileExists,
|
|
||||||
directoryExists: ChakraHost.directoryExists,
|
|
||||||
createDirectory: ChakraHost.createDirectory,
|
|
||||||
getExecutingFilePath: function () { return ChakraHost.executingFile; },
|
|
||||||
getCurrentDirectory: function () { return ChakraHost.currentDirectory; },
|
|
||||||
getDirectories: ChakraHost.getDirectories,
|
|
||||||
getEnvironmentVariable: ChakraHost.getEnvironmentVariable || (function () { return ""; }),
|
|
||||||
readDirectory: function (path, extensions, excludes, includes, _depth) {
|
|
||||||
var pattern = ts.getFileMatcherPatterns(path, excludes, includes, !!ChakraHost.useCaseSensitiveFileNames, ChakraHost.currentDirectory);
|
|
||||||
return ChakraHost.readDirectory(path, extensions, pattern.basePaths, pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern);
|
|
||||||
},
|
|
||||||
exit: ChakraHost.quit,
|
|
||||||
realpath: realpath
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function recursiveCreateDirectory(directoryPath, sys) {
|
|
||||||
var basePath = ts.getDirectoryPath(directoryPath);
|
|
||||||
var shouldCreateParent = basePath !== "" && directoryPath !== basePath && !sys.directoryExists(basePath);
|
|
||||||
if (shouldCreateParent) {
|
|
||||||
recursiveCreateDirectory(basePath, sys);
|
|
||||||
}
|
|
||||||
if (shouldCreateParent || !sys.directoryExists(directoryPath)) {
|
|
||||||
sys.createDirectory(directoryPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var sys;
|
|
||||||
if (typeof ChakraHost !== "undefined") {
|
|
||||||
sys = getChakraSystem();
|
|
||||||
}
|
|
||||||
else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") {
|
|
||||||
// process and process.nextTick checks if current environment is node-like
|
|
||||||
// process.browser check excludes webpack and browserify
|
|
||||||
sys = getNodeSystem();
|
|
||||||
}
|
|
||||||
if (sys) {
|
|
||||||
// patch writefile to create folder before writing the file
|
|
||||||
var originalWriteFile_1 = sys.writeFile;
|
|
||||||
sys.writeFile = function (path, data, writeBom) {
|
|
||||||
var directoryPath = ts.getDirectoryPath(ts.normalizeSlashes(path));
|
|
||||||
if (directoryPath && !sys.directoryExists(directoryPath)) {
|
|
||||||
recursiveCreateDirectory(directoryPath, sys);
|
|
||||||
}
|
|
||||||
originalWriteFile_1.call(sys, path, data, writeBom);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return sys;
|
|
||||||
})();
|
|
||||||
if (ts.sys && ts.sys.getEnvironmentVariable) {
|
if (ts.sys && ts.sys.getEnvironmentVariable) {
|
||||||
setCustomPollingValues(ts.sys);
|
setCustomPollingValues(ts.sys);
|
||||||
ts.Debug.currentAssertionLevel = /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))
|
ts.Debug.currentAssertionLevel = /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue