Skip to content

Commit fe0e980

Browse files
committed
refactor: rework internal logic a little
- make commonjs function with sandbox as a result - skip resolving filename to previous if not passed - throw an error if require or r.resolve used without filename
1 parent b9fe2cb commit fe0e980

2 files changed

Lines changed: 47 additions & 22 deletions

File tree

index.js

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ var Module = require('module');
1111
* @returns {*}
1212
*/
1313
module.exports = function(content, filename, context) {
14-
var ext = path.extname(filename || '');
14+
var ext = filename && path.extname(filename);
1515

1616
content = stripBOM(content);
1717

@@ -22,23 +22,41 @@ module.exports = function(content, filename, context) {
2222
});
2323
}
2424

25-
if(!filename || !path.isAbsolute(filename)) {
26-
filename = path.resolve(path.dirname(_getCalleeFilename()), filename || '');
27-
ext || (ext = path.extname(filename));
25+
if(filename && !path.isAbsolute(filename)) {
26+
filename = path.resolve(path.dirname(_getCalleeFilename()), filename);
2827
}
2928

30-
var dirname = path.dirname(filename);
29+
var sandbox;
30+
sandbox = _commonjsEval(content, filename, context);
31+
32+
var result;
33+
if(sandbox && !sandbox.__result) {
34+
result = sandbox.module.exports;
35+
} else {
36+
result = context ? vm.runInNewContext(content, context) : vm.runInThisContext(content);
37+
}
38+
return result;
39+
};
40+
41+
function _commonjsEval(content, filename, context) {
42+
var dirname = filename && path.dirname(filename);
3143
var sandbox = {};
3244
var exports = {};
3345
var contextKeys;
3446

35-
sandbox.module = new Module(filename, module.parent);
36-
sandbox.module.filename = filename;
47+
sandbox.module = new Module(filename || '<anonymous>', module.parent);
3748
sandbox.module.exports = exports;
38-
sandbox.module.paths = Module._nodeModulePaths(path.dirname(filename));
39-
// See: https://github.com/nodejs/node/blob/master/lib/internal/module.js#L13-L40
40-
sandbox.require = id => sandbox.module.require(id);
41-
sandbox.require.resolve = req => Module._resolveFilename(req, sandbox.module);
49+
50+
if(filename) {
51+
sandbox.module.filename = filename;
52+
sandbox.module.paths = Module._nodeModulePaths(dirname);
53+
// See: https://github.com/nodejs/node/blob/master/lib/internal/module.js#L13-L40
54+
sandbox.require = id => sandbox.module.require(id);
55+
sandbox.require.resolve = req => Module._resolveFilename(req, sandbox.module);
56+
} else {
57+
filename = '<anonymous>';
58+
sandbox.require = filenameRequired;
59+
}
4260

4361
var args = [sandbox.module.exports, sandbox.require, sandbox.module, filename, dirname];
4462
context && (contextKeys = Object.keys(context).map(key => {
@@ -54,19 +72,12 @@ module.exports = function(content, filename, context) {
5472
var exportKeysCount = Object.keys(sandbox.module.exports).length;
5573
compiledWrapper.apply(sandbox.module.exports, args);
5674

57-
var result;
58-
if(
59-
sandbox.module.exports === exports &&
75+
sandbox.__result = sandbox.module.exports === exports &&
6076
Object.keys(sandbox.module.exports).length === exportKeysCount &&
61-
Object.keys(sandbox.module).length === moduleKeysCount
62-
) {
63-
result = context ? vm.runInNewContext(content, context) : vm.runInThisContext(content);
64-
} else {
65-
result = sandbox.module.exports;
66-
}
67-
return result;
68-
};
77+
Object.keys(sandbox.module).length === moduleKeysCount;
6978

79+
return sandbox;
80+
}
7081
/**
7182
* Wrap code with function expression
7283
* Use nodejs style default wrapper
@@ -145,3 +156,7 @@ function parseStackLine(line) {
145156
return {filename: filename, line: parts[2], column: parts[3]};
146157
}
147158

159+
function filenameRequired() {
160+
throw new Error('Please pass in filename to use require');
161+
}
162+
filenameRequired.resolve = filenameRequired;

test/test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,14 @@ describe('errors', () => {
114114

115115
expect(() => nodeEval(content, path)).to.throw(/Unexpected token !/);
116116
});
117+
118+
it('should throw error on require call without filename', function() {
119+
expect(() => nodeEval('exports.path = require("path");'))
120+
.to.throw(/pass in filename/);
121+
});
122+
123+
it('should throw error on require call without filename', function() {
124+
expect(() => nodeEval('exports.path = require.resolve("path");'))
125+
.to.throw(/pass in filename/);
126+
});
117127
});

0 commit comments

Comments
 (0)