summaryrefslogtreecommitdiff
path: root/src/tools/js-wrapper.h
blob: 90453eb357d90b4f2665c400ee09f147d02b1eb6 (plain)
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
/*
 * Copyright 2017 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// Emit a JavaScript wrapper to run a wasm module with some test
// values, useful for fuzzing.
//

namespace wasm {

static std::string generateJSWrapper(Module& wasm) {
  std::string ret;
  ret += "if (typeof console === 'undefined') {\n"
         "  console = { log: print };\n"
         "}\n"
         "var binary;\n"
         "if (typeof process === 'object' && typeof require === 'function' /* node.js detection */) {\n"
         "  var args = process.argv.slice(2);\n"
         "  binary = require('fs').readFileSync(args[0]);\n"
         "  if (!binary.buffer) binary = new Uint8Array(binary);\n"
         "} else {\n"
         "  var args;\n"
         "  if (typeof scriptArgs != 'undefined') {\n"
         "    args = scriptArgs;\n"
         "  } else if (typeof arguments != 'undefined') {\n"
         "    args = arguments;\n"
         "  }\n"
         "  if (typeof readbuffer === 'function') {\n"
         "    binary = new Uint8Array(readbuffer(args[0]));\n"
         "  } else {\n"
         "    binary = read(args[0], 'binary');\n"
         "  }\n"
         "}\n"
         "var instance = new WebAssembly.Instance(new WebAssembly.Module(binary), {});\n";
  for (auto& exp : wasm.exports) {
    auto* func = wasm.getFunctionOrNull(exp->value);
    if (!func) continue; // something exported other than a function
    auto bad = false; // check for things we can't support
    for (WasmType param : func->params) {
      if (param == i64) bad = true;
    }
    if (func->result == i64) bad = true;
    if (bad) continue;
    ret += "if (instance.exports.hangLimitInitializer) instance.exports.hangLimitInitializer();\n";
    ret += "try {\n";
    ret += std::string("  console.log('calling: ") + exp->name.str + "');\n";
    if (func->result != none) {
      ret += "  console.log('   result: ' + ";
    }
    ret += std::string("instance.exports.") + exp->name.str + "(";
    bool first = true;
    for (WasmType param : func->params) {
      WASM_UNUSED(param);
      // zeros in arguments TODO more?
      if (first) {
        first = false;
      } else {
        ret += ", ";
      }
      ret += "0";
    }
    ret += ")";
    if (func->result != none) {
      ret += ")"; // for console.log
    }
    ret += ";\n";
    ret += "} catch (e) {\n";
    ret += "  console.log('   exception: ' + e);\n";
    ret += "}\n";
  }
  ret += "console.log('done.')\n";
  return ret;
}

} // namespace wasm