Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80522 views
1
var parseScope = require('lexical-scope');
2
var through = require('through2');
3
var merge = require('xtend');
4
5
var path = require('path');
6
var processPath = require.resolve('process/browser.js');
7
var combineSourceMap = require('combine-source-map');
8
9
var defaultVars = {
10
process: function () {
11
return 'require(' + JSON.stringify(processPath) + ')';
12
},
13
global: function () {
14
return 'typeof global !== "undefined" ? global : '
15
+ 'typeof self !== "undefined" ? self : '
16
+ 'typeof window !== "undefined" ? window : {}'
17
;
18
},
19
Buffer: function () {
20
return 'require("buffer").Buffer';
21
},
22
__filename: function (file, basedir) {
23
var filename = '/' + path.relative(basedir, file);
24
return JSON.stringify(filename);
25
},
26
__dirname: function (file, basedir) {
27
var dir = path.dirname('/' + path.relative(basedir, file));
28
return JSON.stringify(dir);
29
}
30
};
31
32
module.exports = function (file, opts) {
33
if (/\.json$/i.test(file)) return through();
34
if (!opts) opts = {};
35
36
var basedir = opts.basedir || '/';
37
var vars = merge(defaultVars, opts.vars);
38
var varNames = Object.keys(vars);
39
40
var quick = RegExp(varNames.map(function (name) {
41
return '\\b' + name + '\\b';
42
}).join('|'));
43
44
var chunks = [];
45
46
return through(write, end);
47
48
function write (chunk, enc, next) { chunks.push(chunk); next() }
49
50
function end () {
51
var self = this;
52
var source = Buffer.isBuffer(chunks[0])
53
? Buffer.concat(chunks).toString('utf8')
54
: chunks.join('')
55
;
56
source = source
57
.replace(/^\ufeff/, '')
58
.replace(/^#![^\n]*\n/, '\n');
59
60
if (opts.always !== true && !quick.test(source)) {
61
this.push(source);
62
this.push(null);
63
return;
64
}
65
66
try {
67
var scope = opts.always
68
? { globals: { implicit: varNames } }
69
: parseScope('(function(){\n' + source + '\n})()')
70
;
71
}
72
catch (err) {
73
var e = new SyntaxError(
74
(err.message || err) + ' while parsing ' + file
75
);
76
e.type = 'syntax';
77
e.filename = file;
78
return this.emit('error', e);
79
}
80
81
var globals = {};
82
83
varNames.forEach(function (name) {
84
if (scope.globals.implicit.indexOf(name) >= 0) {
85
var value = vars[name](file, basedir);
86
if (value) {
87
globals[name] = value;
88
self.emit('global', name);
89
}
90
}
91
});
92
93
this.push(closeOver(globals, source, file, opts));
94
this.push(null);
95
}
96
};
97
98
module.exports.vars = defaultVars;
99
100
function closeOver (globals, src, file, opts) {
101
var keys = Object.keys(globals);
102
if (keys.length === 0) return src;
103
var values = keys.map(function (key) { return globals[key] });
104
105
var wrappedSource;
106
if (keys.length <= 3) {
107
wrappedSource = '(function (' + keys.join(',') + '){\n'
108
+ src + '\n}).call(this,' + values.join(',') + ')'
109
;
110
}
111
else {
112
// necessary to make arguments[3..6] still work for workerify etc
113
// a,b,c,arguments[3..6],d,e,f...
114
var extra = [ '__argument0', '__argument1', '__argument2', '__argument3' ];
115
var names = keys.slice(0,3).concat(extra).concat(keys.slice(3));
116
values.splice(3, 0,
117
'arguments[3]','arguments[4]',
118
'arguments[5]','arguments[6]'
119
);
120
wrappedSource = '(function (' + names.join(',') + '){\n'
121
+ src + '\n}).call(this,' + values.join(',') + ')';
122
}
123
124
// Generate source maps if wanted. Including the right offset for
125
// the wrapped source.
126
if (!opts.debug) {
127
return wrappedSource;
128
}
129
var sourceFile = path.relative(opts.basedir, file)
130
.replace(/\\/g, '/');
131
var sourceMap = combineSourceMap.create().addFile(
132
{ sourceFile: sourceFile, source: src},
133
{ line: 1 });
134
return combineSourceMap.removeComments(wrappedSource) + "\n"
135
+ sourceMap.comment();
136
}
137
138