From 42b79f08239216eeea3cc1b0febc992f91bd88de Mon Sep 17 00:00:00 2001
From: Richard Musiol <mail@richard-musiol.de>
Date: Wed, 26 Dec 2018 13:34:47 +0100
Subject: [PATCH] misc/wasm: better adapt to different JavaScript environments

This change adds support for using wasm with Electron. It refactors
environment detection to a more modular approach instead of explicitly
testing for Node.js.

Fixes #29404

Change-Id: I882a9c56523744e7fd7cb2013d158df91cf91d14
Reviewed-on: https://go-review.googlesource.com/c/164665
Run-TryBot: Richard Musiol <neelance@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
---
 misc/wasm/wasm_exec.js | 72 +++++++++++++++++++++++++++++-------------
 1 file changed, 50 insertions(+), 22 deletions(-)

diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js
index 165d5677505..8eff751d62a 100644
--- a/misc/wasm/wasm_exec.js
+++ b/misc/wasm/wasm_exec.js
@@ -3,6 +3,15 @@
 // license that can be found in the LICENSE file.
 
 (() => {
+	// Map multiple JavaScript environments to a single common API,
+	// preferring web standards over Node.js API.
+	//
+	// Environments considered:
+	// - Browsers
+	// - Node.js
+	// - Electron
+	// - Parcel
+
 	if (typeof global !== "undefined") {
 		// global already exists
 	} else if (typeof window !== "undefined") {
@@ -13,30 +22,15 @@
 		throw new Error("cannot export Go (neither global, window nor self is defined)");
 	}
 
-	// Map web browser API and Node.js API to a single common API (preferring web standards over Node.js API).
-	const isNodeJS = global.process && global.process.title === "node";
-	if (isNodeJS) {
+	if (!global.require && typeof require !== "undefined") {
 		global.require = require;
-		global.fs = require("fs");
-
-		const nodeCrypto = require("crypto");
-		global.crypto = {
-			getRandomValues(b) {
-				nodeCrypto.randomFillSync(b);
-			},
-		};
+	}
 
-		global.performance = {
-			now() {
-				const [sec, nsec] = process.hrtime();
-				return sec * 1000 + nsec / 1000000;
-			},
-		};
+	if (!global.fs && global.require) {
+		global.fs = require("fs");
+	}
 
-		const util = require("util");
-		global.TextEncoder = util.TextEncoder;
-		global.TextDecoder = util.TextDecoder;
-	} else {
+	if (!global.fs) {
 		let outputBuf = "";
 		global.fs = {
 			constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
@@ -72,6 +66,34 @@
 		};
 	}
 
+	if (!global.crypto) {
+		const nodeCrypto = require("crypto");
+		global.crypto = {
+			getRandomValues(b) {
+				nodeCrypto.randomFillSync(b);
+			},
+		};
+	}
+
+	if (!global.performance) {
+		global.performance = {
+			now() {
+				const [sec, nsec] = process.hrtime();
+				return sec * 1000 + nsec / 1000000;
+			},
+		};
+	}
+
+	if (!global.TextEncoder) {
+		global.TextEncoder = require("util").TextEncoder;
+	}
+
+	if (!global.TextDecoder) {
+		global.TextDecoder = require("util").TextDecoder;
+	}
+
+	// End of polyfills for common API.
+
 	const encoder = new TextEncoder("utf-8");
 	const decoder = new TextDecoder("utf-8");
 
@@ -439,7 +461,13 @@
 		}
 	}
 
-	if (isNodeJS) {
+	if (
+		global.require &&
+		global.require.main === module &&
+		global.process &&
+		global.process.versions &&
+		!global.process.versions.electron
+	) {
 		if (process.argv.length < 3) {
 			process.stderr.write("usage: go_js_wasm_exec [wasm binary] [arguments]\n");
 			process.exit(1);
-- 
GitLab