Skip to content

Commit dcd784e

Browse files
committed
adopt new loader, fixes microsoft#25229
1 parent 3782c32 commit dcd784e

1 file changed

Lines changed: 105 additions & 40 deletions

File tree

src/vs/loader.js

Lines changed: 105 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -583,24 +583,86 @@ var AMDLoader;
583583
}());
584584
var NodeScriptLoader = (function () {
585585
function NodeScriptLoader() {
586-
this._initialized = false;
586+
this._didInitialize = false;
587+
this._didPatchNodeRequire = false;
588+
// js-flags have an impact on cached data
589+
this._jsflags = '';
590+
for (var _i = 0, _a = process.argv; _i < _a.length; _i++) {
591+
var arg = _a[_i];
592+
if (arg.indexOf('--js-flags=') === 0) {
593+
this._jsflags = arg;
594+
break;
595+
}
596+
}
587597
}
588598
NodeScriptLoader.prototype._init = function (nodeRequire) {
589-
if (this._initialized) {
599+
if (this._didInitialize) {
590600
return;
591601
}
592-
this._initialized = true;
602+
this._didInitialize = true;
593603
this._fs = nodeRequire('fs');
594604
this._vm = nodeRequire('vm');
595605
this._path = nodeRequire('path');
596606
this._crypto = nodeRequire('crypto');
597607
};
608+
// patch require-function of nodejs such that we can manually create a script
609+
// from cached data. this is done by overriding the `Module._compile` function
610+
NodeScriptLoader.prototype._initNodeRequire = function (nodeRequire, moduleManager) {
611+
var nodeCachedDataDir = moduleManager.getConfig().getOptionsLiteral().nodeCachedDataDir;
612+
if (!nodeCachedDataDir || this._didPatchNodeRequire) {
613+
return;
614+
}
615+
this._didPatchNodeRequire = true;
616+
var that = this;
617+
var Module = nodeRequire('module');
618+
function makeRequireFunction(mod) {
619+
var Module = mod.constructor;
620+
var require = function require(path) {
621+
try {
622+
return mod.require(path);
623+
}
624+
finally {
625+
// nothing
626+
}
627+
};
628+
require.resolve = function resolve(request) {
629+
return Module._resolveFilename(request, mod);
630+
};
631+
require.main = process.mainModule;
632+
require.extensions = Module._extensions;
633+
require.cache = Module._cache;
634+
return require;
635+
}
636+
Module.prototype._compile = function (content, filename) {
637+
// remove shebang
638+
content = content.replace(/^#!.*/, '');
639+
// create wrapper function
640+
var wrapper = Module.wrap(content);
641+
var cachedDataPath = that._getCachedDataPath(nodeCachedDataDir, filename);
642+
var options = { filename: filename };
643+
try {
644+
options.cachedData = that._fs.readFileSync(cachedDataPath);
645+
}
646+
catch (e) {
647+
options.produceCachedData = true;
648+
}
649+
var script = new that._vm.Script(wrapper, options);
650+
var compileWrapper = script.runInThisContext(options);
651+
var dirname = that._path.dirname(filename);
652+
var require = makeRequireFunction(this);
653+
var args = [this.exports, require, this, filename, dirname, process, AMDLoader.global, Buffer];
654+
var result = compileWrapper.apply(this.exports, args);
655+
that._processCachedData(moduleManager, script, cachedDataPath);
656+
return result;
657+
};
658+
};
598659
NodeScriptLoader.prototype.load = function (moduleManager, scriptSrc, callback, errorback) {
599660
var _this = this;
600661
var opts = moduleManager.getConfig().getOptionsLiteral();
601662
var nodeRequire = (opts.nodeRequire || AMDLoader.global.nodeRequire);
602663
var nodeInstrumenter = (opts.nodeInstrumenter || function (c) { return c; });
603664
this._init(nodeRequire);
665+
this._initNodeRequire(nodeRequire, moduleManager);
604666
var recorder = moduleManager.getRecorder();
605667
if (/^node\|/.test(scriptSrc)) {
606668
var pieces = scriptSrc.split('|');
@@ -646,44 +708,16 @@ var AMDLoader;
646708
}
647709
else {
648710
var cachedDataPath_1 = _this._getCachedDataPath(opts.nodeCachedDataDir, scriptSrc);
649-
_this._fs.readFile(cachedDataPath_1, function (err, data) {
711+
_this._fs.readFile(cachedDataPath_1, function (err, cachedData) {
650712
// create script options
651-
var scriptOptions = {
713+
var options = {
652714
filename: vmScriptSrc,
653-
produceCachedData: typeof data === 'undefined',
654-
cachedData: data
715+
produceCachedData: typeof cachedData === 'undefined',
716+
cachedData: cachedData
655717
};
656-
var script = _this._loadAndEvalScript(scriptSrc, vmScriptSrc, contents, scriptOptions, recorder);
718+
var script = _this._loadAndEvalScript(scriptSrc, vmScriptSrc, contents, options, recorder);
657719
callback();
658-
// cached code after math
659-
if (script.cachedDataRejected) {
660-
// data rejected => delete cache file
661-
opts.onNodeCachedDataError({
662-
errorCode: 'cachedDataRejected',
663-
path: cachedDataPath_1
664-
});
665-
NodeScriptLoader._runSoon(function () { return _this._fs.unlink(cachedDataPath_1, function (err) {
666-
if (err) {
667-
moduleManager.getConfig().getOptionsLiteral().onNodeCachedDataError({
668-
errorCode: 'unlink',
669-
path: cachedDataPath_1,
670-
detail: err
671-
});
672-
}
673-
}); }, opts.nodeCachedDataWriteDelay);
674-
}
675-
else if (script.cachedDataProduced) {
676-
// data produced => write cache file
677-
NodeScriptLoader._runSoon(function () { return _this._fs.writeFile(cachedDataPath_1, script.cachedData, function (err) {
678-
if (err) {
679-
moduleManager.getConfig().getOptionsLiteral().onNodeCachedDataError({
680-
errorCode: 'writeFile',
681-
path: cachedDataPath_1,
682-
detail: err
683-
});
684-
}
685-
}); }, opts.nodeCachedDataWriteDelay);
686-
}
720+
_this._processCachedData(moduleManager, script, cachedDataPath_1);
687721
});
688722
}
689723
});
@@ -699,10 +733,41 @@ var AMDLoader;
699733
recorder.record(AMDLoader.LoaderEventType.NodeEndEvaluatingScript, scriptSrc);
700734
return script;
701735
};
702-
NodeScriptLoader.prototype._getCachedDataPath = function (baseDir, filename) {
703-
var hash = this._crypto.createHash('md5').update(filename, 'utf8').digest('hex');
736+
NodeScriptLoader.prototype._getCachedDataPath = function (basedir, filename) {
737+
var hash = this._crypto.createHash('md5').update(filename, 'utf8').update(this._jsflags, 'utf8').digest('hex');
704738
var basename = this._path.basename(filename).replace(/\.js$/, '');
705-
return this._path.join(baseDir, hash + "-" + basename + ".code");
739+
return this._path.join(basedir, basename + "-" + hash + ".code");
740+
};
741+
NodeScriptLoader.prototype._processCachedData = function (moduleManager, script, cachedDataPath) {
742+
var _this = this;
743+
if (script.cachedDataRejected) {
744+
// data rejected => delete cache file
745+
moduleManager.getConfig().getOptionsLiteral().onNodeCachedDataError({
746+
errorCode: 'cachedDataRejected',
747+
path: cachedDataPath
748+
});
749+
NodeScriptLoader._runSoon(function () { return _this._fs.unlink(cachedDataPath, function (err) {
750+
if (err) {
751+
moduleManager.getConfig().getOptionsLiteral().onNodeCachedDataError({
752+
errorCode: 'unlink',
753+
path: cachedDataPath,
754+
detail: err
755+
});
756+
}
757+
}); }, moduleManager.getConfig().getOptionsLiteral().nodeCachedDataWriteDelay);
758+
}
759+
else if (script.cachedDataProduced) {
760+
// data produced => write cache file
761+
NodeScriptLoader._runSoon(function () { return _this._fs.writeFile(cachedDataPath, script.cachedData, function (err) {
762+
if (err) {
763+
moduleManager.getConfig().getOptionsLiteral().onNodeCachedDataError({
764+
errorCode: 'writeFile',
765+
path: cachedDataPath,
766+
detail: err
767+
});
768+
}
769+
}); }, moduleManager.getConfig().getOptionsLiteral().nodeCachedDataWriteDelay);
770+
}
706771
};
707772
NodeScriptLoader._runSoon = function (callback, minTimeout) {
708773
var timeout = minTimeout + Math.ceil(Math.random() * minTimeout);

0 commit comments

Comments
 (0)