UNPKG

2.5 kBJavaScriptView Raw
1'use strict';
2
3const t = require('babel-types');
4const path = require('path');
5const generate = require('babel-generator').default;
6const vm = require('vm');
7
8const canEvaluate = require('./canEvaluate');
9const canEvaluateObject = require('./canEvaluateObject');
10const getSourceModule = require('./getSourceModule');
11
12function getStaticBindingsForScope(scope, whitelist = [], sourceFileName) {
13 const bindings = scope.getAllBindings();
14 const ret = {};
15
16 const sourceDir = path.dirname(sourceFileName);
17
18 for (const k in bindings) {
19 const binding = bindings[k];
20
21 // check to see if the item is a module
22 const sourceModule = getSourceModule(k, binding);
23 if (sourceModule) {
24 let moduleName = sourceModule.sourceModule;
25
26 // if modulePath is an absolute or relative path
27 if (
28 sourceModule.sourceModule.startsWith('.') ||
29 sourceModule.sourceModule.startsWith('/')
30 ) {
31 // if moduleName doesn't end with an extension, add .js
32 if (path.extname(moduleName) === '') {
33 moduleName += '.js';
34 }
35 // get absolute path
36 moduleName = path.resolve(sourceDir, moduleName);
37 }
38
39 if (whitelist.indexOf(moduleName) > -1) {
40 const src = require(moduleName);
41 if (sourceModule.destructured) {
42 ret[k] = src[sourceModule.imported];
43 } else {
44 // crude esmodule check
45 // TODO: make sure this actually works
46 if (src && src.__esModule) {
47 ret[k] = src.default;
48 } else {
49 ret[k] = src;
50 }
51 }
52 }
53 continue;
54 } else if (
55 t.isVariableDeclaration(binding.path.parent) &&
56 binding.path.parent.kind === 'const'
57 ) {
58 // pick out the right variable declarator
59 const dec = binding.path.parent.declarations.find(
60 d => t.isIdentifier(d.id) && d.id.name === k
61 );
62 // TODO: handle spread syntax
63 if (!dec) continue;
64
65 if (
66 canEvaluate(null, dec.init) ||
67 // if dec.init is an object defined in the program root, evaluate it
68 // NOTE: this assumes that objects defined in the program root are not mutated!
69 // TODO: make this behaviour opt-in (?)
70 (binding.path.parentPath.parentPath.type === 'Program' &&
71 canEvaluateObject(null, dec.init))
72 ) {
73 ret[k] = vm.runInNewContext('(' + generate(dec.init).code + ')');
74 }
75 }
76 }
77
78 return ret;
79}
80
81module.exports = getStaticBindingsForScope;