Add example of using source-map-support (#130)

Add example of using source-map-support (#130)

  • Add example of using source-map-support

  • Address PR comments

diff --git a/README.md b/README.md
index 8b8a62d..e0dc6cf 100644
--- a/README.md
+++ b/README.md
@@ -346,6 +346,10 @@ Note how the global interpreter lock release leads to 2 threads doing the same w
 
 As a rule MiniRacer strives to always support and depend on the latest stable version of libv8.
 
+## Source Maps
+
+MiniRacer can fully support source maps but must be configured correctly to do so. [Check out this example](./examples/source-map-support/) for a working implementation.
+
 ## Installation
 
 Add this line to your application's Gemfile:
diff --git a/examples/source-map-support/.gitignore b/examples/source-map-support/.gitignore
new file mode 100644
index 0000000..f06235c
--- /dev/null
+++ b/examples/source-map-support/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+dist
diff --git a/examples/source-map-support/error-causing-component.jsx b/examples/source-map-support/error-causing-component.jsx
new file mode 100644
index 0000000..19c77c0
--- /dev/null
+++ b/examples/source-map-support/error-causing-component.jsx
@@ -0,0 +1,9 @@
+function throwSomeError() {
+  throw new Error(
+    "^^ Look! These stack traces map to the actual source code :)"
+  );
+}
+
+export const ErrorCausingComponent = () => {
+  throwSomeError();
+};
diff --git a/examples/source-map-support/index.jsx b/examples/source-map-support/index.jsx
new file mode 100644
index 0000000..ce80f1e
--- /dev/null
+++ b/examples/source-map-support/index.jsx
@@ -0,0 +1,20 @@
+import { ErrorCausingComponent } from "./error-causing-component.jsx";
+
+if (process.env.NODE_ENV === "production") {
+  require("source-map-support").install({
+    // We tell the source-map-support package to retrieve our source maps by
+    // calling the `readSourceMap` global function, which we attached to the
+    // miniracer context
+    retrieveSourceMap: filename => {
+      return {
+        url: filename,
+        map: readSourceMap(filename)
+      };
+    }
+  });
+}
+
+// We expose this function so we can call it later
+export function renderComponent() {
+  ErrorCausingComponent();
+}
diff --git a/examples/source-map-support/package.json b/examples/source-map-support/package.json
new file mode 100644
index 0000000..dbba106
--- /dev/null
+++ b/examples/source-map-support/package.json
@@ -0,0 +1,19 @@
+{
+  "name": "mini-racer-source-map-support-example",
+  "version": "1.0.0",
+  "main": "index.js",
+  "license": "MIT",
+  "devDependencies": {
+    "@babel/core": "^7.3.4",
+    "babel-loader": "^8.0.5",
+    "prettier": "^1.16.4",
+    "webpack": "^4.29.6",
+    "webpack-cli": "^3.2.3"
+  },
+  "scripts": {
+    "build": "webpack"
+  },
+  "dependencies": {
+    "source-map-support": "^0.5.10"
+  }
+}
diff --git a/examples/source-map-support/readme.md b/examples/source-map-support/readme.md
new file mode 100644
index 0000000..6c55d4a
--- /dev/null
+++ b/examples/source-map-support/readme.md
@@ -0,0 +1,30 @@
+# Source Map Support
+
+This example shows how to map source maps using webpack. Webpack production
+builds will compile and minify code aggressively, so source maps are very
+important when debugging production issues. This example shows how to give
+readable stack traces to make debugging easier.
+
+## Running the example
+
+1. Install the dependencies: `yarn install`
+2. Build the js bundle: `yarn build`
+3. Run the ruby code which triggers an error: `bundle exec ruby renderer.rb`
+
+After running that, you will see the correct source code locations where the
+error occurred. The result will intentionally throw an error which looks like:
+
+`‍``
+Traceback (most recent call last):
+        10: from renderer.rb:12:in `<main>'
+         9: from /home/ianks/Development/adhawk/mini_racer/lib/mini_racer.rb:176:in `eval'
+         8: from /home/ianks/Development/adhawk/mini_racer/lib/mini_racer.rb:176:in `synchronize'
+         7: from /home/ianks/Development/adhawk/mini_racer/lib/mini_racer.rb:178:in `block in eval'
+         6: from /home/ianks/Development/adhawk/mini_racer/lib/mini_racer.rb:264:in `timeout'
+         5: from /home/ianks/Development/adhawk/mini_racer/lib/mini_racer.rb:179:in `block (2 levels) in eval'
+         4: from /home/ianks/Development/adhawk/mini_racer/lib/mini_racer.rb:179:in `eval_unsafe'
+         3: from JavaScript at <anonymous>:1:17
+         2: from JavaScript at Module.ErrorCausingComponent (/webpack:/webpackLib/index.jsx:19:3)
+         1: from JavaScript at throwSomeError (/webpack:/webpackLib/error-causing-component.jsx:8:3)
+JavaScript at /webpack:/webpackLib/error-causing-component.jsx:2:9: Error: ^^ Look! These stack traces map to the actual source code :) (MiniRacer::RuntimeError)
+`‍``
diff --git a/examples/source-map-support/renderer.rb b/examples/source-map-support/renderer.rb
new file mode 100644
index 0000000..8fcbfdb
--- /dev/null
+++ b/examples/source-map-support/renderer.rb
@@ -0,0 +1,12 @@
+require 'mini_racer'
+
+ctx = MiniRacer::Context.new
+
+# Make sure we pass the filename option so source-map-support can map properly
+ctx.eval(File.read('./dist/main.js'), filename: 'main.js')
+
+# Expose a function to retrieve the source map
+ctx.attach('readSourceMap', proc { |filename| File.read("./dist/#{filename}.map")} )
+
+# This will actually cause the error, and we will have a pretty backtrace!
+ctx.eval('this.webpackLib.renderComponent()')
diff --git a/examples/source-map-support/webpack.config.js b/examples/source-map-support/webpack.config.js
new file mode 100644
index 0000000..67de22d
--- /dev/null
+++ b/examples/source-map-support/webpack.config.js
@@ -0,0 +1,25 @@
+module.exports = {
+  mode: "production",
+  entry: "./index.jsx",
+  // This will put our source maps in a seperate .map file which we will read
+  // later
+  devtool: "source-map",
+  module: {
+    rules: [
+      {
+        test: /\.jsx?$/,
+        exclude: /node_modules/,
+        use: {
+          loader: "babel-loader"
+        }
+      }
+    ]
+  },
+  output: {
+    library: "webpackLib",
+    libraryTarget: "umd",
+    // This is necessary to make webpack not define globals on the non-existent
+    // 'window' object
+    globalObject: "this"
+  }
+};
diff --git a/examples/source-map-support/yarn.lock b/examples/source-map-support/yarn.lock
new file mode 100644
index 0000000..5fcc490
--- /dev/null
+++ b/examples/source-map-support/yarn.lock
@@ -0,0 +1,3252 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/code-frame@^7.0.0":
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8"
+  integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==
+  dependencies:
+    "@babel/highlight" "^7.0.0"
+
+"@babel/core@^7.3.4":
+  version "7.3.4"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b"
+  integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    "@babel/generator" "^7.3.4"
+    "@babel/helpers" "^7.2.0"
+    "@babel/parser" "^7.3.4"
+    "@babel/template" "^7.2.2"
+    "@babel/traverse" "^7.3.4"
+    "@babel/types" "^7.3.4"
+    convert-source-map "^1.1.0"
+    debug "^4.1.0"
+    json5 "^2.1.0"
+    lodash "^4.17.11"
+    resolve "^1.3.2"
+    semver "^5.4.1"
+    source-map "^0.5.0"
+
+"@babel/generator@^7.3.4":
+  version "7.3.4"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e"
+  integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==
+  dependencies:
+    "@babel/types" "^7.3.4"
+    jsesc "^2.5.1"
+    lodash "^4.17.11"
+    source-map "^0.5.0"
+    trim-right "^1.0.1"
+
+"@babel/helper-builder-react-jsx@^7.3.0":
+  version "7.3.0"

[... diff too long, it was truncated ...]

GitHub sha: 723958f4