-
Notifications
You must be signed in to change notification settings - Fork 9
/
index.es6.js
104 lines (84 loc) · 3.27 KB
/
index.es6.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
require("./vendor/opal-compiler.js")
import process from "process"
import loaderUtils from "loader-utils"
import { SourceNode, SourceMapConsumer, SourceMapGenerator } from 'source-map'
import path from "path"
import fs from "fs";
const LOAD_PATH = process.env.OPAL_LOAD_PATH ? process.env.OPAL_LOAD_PATH.split(":") : [];
if (LOAD_PATH.length === 0) {
console.warn("OPAL_LOAD_PATH environment variable is not set")
console.warn("By default, loader will only load from path relative to current source")
}
function getCurrentLoader(loaderContext) {
return loaderContext.loaders[loaderContext.loaderIndex];
}
function resolveFilename(loaderContext, filename) {
let rubyFileName = filename.replace(/(\.rb)?$/, ".rb");
// FIXME
// Workaround to make "require 'opal'" work, original opal will try to concate raw js
if (filename == 'corelib/runtime') {
rubyFileName = 'corelib/runtime.js'
}
let result = null;
if (rubyFileName.match(/^\./)) {
// Resolve in current directory
let fullPath = path.resolve(loaderContext.context, rubyFileName);
if (fs.existsSync(fullPath)) {
result = fullPath;
}
} else {
// Resolve in LOAD_PATH
for (var dir of LOAD_PATH) {
let fullPath = path.resolve(dir, rubyFileName);
if (fs.existsSync(fullPath)) {
result = fullPath;
break;
}
}
}
if (result) {
return result;
} else {
throw new Error(`Cannot load file - ${filename}`);
}
}
module.exports = function(source) {
const callback = this.async();
if(!callback) throw new Error("Sync mode not supported");
const compilerOptions = Object.assign({file: this.resourcePath}, loaderUtils.parseQuery(this.query));
const compiler = Opal.Opal.Compiler.$new(source, Opal.hash(compilerOptions));
const currentLoader = getCurrentLoader(this).path;
this.cacheable && this.cacheable()
compiler.$compile();
const result = compiler.$result();
/*
Workaround to make IO work,
webpack polyfill global "process" module by default,
while Opal::IO rely on it to deterimine in node environment or not
*/
let prepend = ['process = undefined;'];
compiler.$requires().forEach(filename => {
var resolved = resolveFilename(this, filename);
if (resolved.match(/\.js$/)) {
prepend.push(`require('${require.resolve('imports-loader')}!${resolved}');`);
prepend.push(`Opal.loaded('${filename}');`)
} else {
prepend.push(`require('!!${currentLoader}?file=${filename}&requirable=true!${resolved}');`);
}
})
if (this.sourceMap) {
let rawMap = JSON.parse(compiler.$source_map().$as_json().$to_json());
// Since it's compiled from the current resource
rawMap.sources = [this.resourcePath];
// Set source content
let consumer = new SourceMapConsumer(rawMap)
let map = SourceMapGenerator.fromSourceMap(consumer);
map.setSourceContent(this.resourcePath, source);
// Prepend the chunk of our injected script
let node = SourceNode.fromStringWithSourceMap(result, new SourceMapConsumer(map.toString()));
node.prepend(prepend.join(" "));
callback(null, prepend.join(" ") + "\n" + result, JSON.parse(node.toStringWithSourceMap().map.toString()));
} else {
callback(null, prepend.join(" ") + "\n" + result);
}
};