Browse Source

Support WebAssembly types in Jsrt debugger.
Fix Marshaling for WebAssemblyModule and WebAssemblyInstance
Add more wasm debugger test

Michael Ferris 8 năm trước cách đây
mục cha
commit
acafcbb650

+ 52 - 68
bin/ch/Helpers.cpp

@@ -252,74 +252,58 @@ LPCWSTR Helpers::JsErrorCodeToString(JsErrorCode jsErrorCode)
 
     switch (jsErrorCode)
     {
-    case JsNoError:
-        return _u("JsNoError");
-        break;
-
-    case JsErrorInvalidArgument:
-        return _u("JsErrorInvalidArgument");
-        break;
-
-    case JsErrorNullArgument:
-        return _u("JsErrorNullArgument");
-        break;
-
-    case JsErrorNoCurrentContext:
-        return _u("JsErrorNoCurrentContext");
-        break;
-
-    case JsErrorInExceptionState:
-        return _u("JsErrorInExceptionState");
-        break;
-
-    case JsErrorNotImplemented:
-        return _u("JsErrorNotImplemented");
-        break;
-
-    case JsErrorWrongThread:
-        return _u("JsErrorWrongThread");
-        break;
-
-    case JsErrorRuntimeInUse:
-        return _u("JsErrorRuntimeInUse");
-        break;
-
-    case JsErrorBadSerializedScript:
-        return _u("JsErrorBadSerializedScript");
-        break;
-
-    case JsErrorInDisabledState:
-        return _u("JsErrorInDisabledState");
-        break;
-
-    case JsErrorCannotDisableExecution:
-        return _u("JsErrorCannotDisableExecution");
-        break;
-
-    case JsErrorHeapEnumInProgress:
-        return _u("JsErrorHeapEnumInProgress");
-        break;
-
-    case JsErrorOutOfMemory:
-        return _u("JsErrorOutOfMemory");
-        break;
-
-    case JsErrorScriptException:
-        return _u("JsErrorScriptException");
-        break;
-
-    case JsErrorScriptCompile:
-        return _u("JsErrorScriptCompile");
-        break;
-
-    case JsErrorScriptTerminated:
-        return _u("JsErrorScriptTerminated");
-        break;
-
-    case JsErrorFatal:
-        return _u("JsErrorFatal");
-        break;
-
+    case JsNoError:                            return _u("JsNoError");
+    // JsErrorCategoryUsage
+    case JsErrorCategoryUsage:                 return _u("JsErrorCategoryUsage");
+    case JsErrorInvalidArgument:               return _u("JsErrorInvalidArgument");
+    case JsErrorNullArgument:                  return _u("JsErrorNullArgument");
+    case JsErrorNoCurrentContext:              return _u("JsErrorNoCurrentContext");
+    case JsErrorInExceptionState:              return _u("JsErrorInExceptionState");
+    case JsErrorNotImplemented:                return _u("JsErrorNotImplemented");
+    case JsErrorWrongThread:                   return _u("JsErrorWrongThread");
+    case JsErrorRuntimeInUse:                  return _u("JsErrorRuntimeInUse");
+    case JsErrorBadSerializedScript:           return _u("JsErrorBadSerializedScript");
+    case JsErrorInDisabledState:               return _u("JsErrorInDisabledState");
+    case JsErrorCannotDisableExecution:        return _u("JsErrorCannotDisableExecution");
+    case JsErrorHeapEnumInProgress:            return _u("JsErrorHeapEnumInProgress");
+    case JsErrorArgumentNotObject:             return _u("JsErrorArgumentNotObject");
+    case JsErrorInProfileCallback:             return _u("JsErrorInProfileCallback");
+    case JsErrorInThreadServiceCallback:       return _u("JsErrorInThreadServiceCallback");
+    case JsErrorCannotSerializeDebugScript:    return _u("JsErrorCannotSerializeDebugScript");
+    case JsErrorAlreadyDebuggingContext:       return _u("JsErrorAlreadyDebuggingContext");
+    case JsErrorAlreadyProfilingContext:       return _u("JsErrorAlreadyProfilingContext");
+    case JsErrorIdleNotEnabled:                return _u("JsErrorIdleNotEnabled");
+    case JsCannotSetProjectionEnqueueCallback: return _u("JsCannotSetProjectionEnqueueCallback");
+    case JsErrorCannotStartProjection:         return _u("JsErrorCannotStartProjection");
+    case JsErrorInObjectBeforeCollectCallback: return _u("JsErrorInObjectBeforeCollectCallback");
+    case JsErrorObjectNotInspectable:          return _u("JsErrorObjectNotInspectable");
+    case JsErrorPropertyNotSymbol:             return _u("JsErrorPropertyNotSymbol");
+    case JsErrorPropertyNotString:             return _u("JsErrorPropertyNotString");
+    case JsErrorInvalidContext:                return _u("JsErrorInvalidContext");
+    case JsInvalidModuleHostInfoKind:          return _u("JsInvalidModuleHostInfoKind");
+    case JsErrorModuleParsed:                  return _u("JsErrorModuleParsed");
+    // JsErrorCategoryEngine
+    case JsErrorCategoryEngine:                return _u("JsErrorCategoryEngine");
+    case JsErrorOutOfMemory:                   return _u("JsErrorOutOfMemory");
+    case JsErrorBadFPUState:                   return _u("JsErrorBadFPUState");
+    // JsErrorCategoryScript
+    case JsErrorCategoryScript:                return _u("JsErrorCategoryScript");
+    case JsErrorScriptException:               return _u("JsErrorScriptException");
+    case JsErrorScriptCompile:                 return _u("JsErrorScriptCompile");
+    case JsErrorScriptTerminated:              return _u("JsErrorScriptTerminated");
+    case JsErrorScriptEvalDisabled:            return _u("JsErrorScriptEvalDisabled");
+    // JsErrorCategoryFatal
+    case JsErrorCategoryFatal:                 return _u("JsErrorCategoryFatal");
+    case JsErrorFatal:                         return _u("JsErrorFatal");
+    case JsErrorWrongRuntime:                  return _u("JsErrorWrongRuntime");
+    // JsErrorCategoryDiagError
+    case JsErrorCategoryDiagError:             return _u("JsErrorCategoryDiagError");
+    case JsErrorDiagAlreadyInDebugMode:        return _u("JsErrorDiagAlreadyInDebugMode");
+    case JsErrorDiagNotInDebugMode:            return _u("JsErrorDiagNotInDebugMode");
+    case JsErrorDiagNotAtBreak:                return _u("JsErrorDiagNotAtBreak");
+    case JsErrorDiagInvalidHandle:             return _u("JsErrorDiagInvalidHandle");
+    case JsErrorDiagObjectNotFound:            return _u("JsErrorDiagObjectNotFound");
+    case JsErrorDiagUnableToPerformAction:     return _u("JsErrorDiagUnableToPerformAction");
     default:
         return _u("<unknown>");
         break;

+ 12 - 1
lib/Jsrt/JsrtDebugUtils.cpp

@@ -278,6 +278,12 @@ void JsrtDebugUtils::AddPropertyType(Js::DynamicObject * object, Js::IDiagObject
         case Js::TypeIds_Promise:
         case Js::TypeIds_GlobalObject:
         case Js::TypeIds_SpreadArgument:
+#ifdef ENABLE_WASM
+        case Js::TypeIds_WebAssemblyModule:
+        case Js::TypeIds_WebAssemblyInstance:
+        case Js::TypeIds_WebAssemblyMemory:
+        case Js::TypeIds_WebAssemblyTable:
+#endif
 
         case Js::TypeIds_Proxy:
         {
@@ -467,7 +473,12 @@ const char16 * JsrtDebugUtils::GetClassName(Js::TypeId typeId)
     case Js::TypeIds_Promise:           return _u("Promise");
     case Js::TypeIds_GlobalObject:      return _u("Object");
     case Js::TypeIds_SpreadArgument:    return _u("Spread");
-
+#ifdef ENABLE_WASM
+    case Js::TypeIds_WebAssemblyModule:  return _u("WebAssembly.Module");
+    case Js::TypeIds_WebAssemblyInstance:return _u("WebAssembly.Instance");
+    case Js::TypeIds_WebAssemblyMemory:  return _u("WebAssembly.Memory");
+    case Js::TypeIds_WebAssemblyTable:   return _u("WebAssembly.Table");
+#endif
     default:
         Assert(false);
     }

+ 2 - 0
lib/Runtime/Library/ScriptFunction.h

@@ -143,7 +143,9 @@ namespace Js
 
     private:
         Field(Field(Var)*) m_moduleMemory;
+#ifdef ENABLE_WASM
         Field(Wasm::WasmSignature *) m_signature;
+#endif
     };
 
     class ScriptFunctionWithInlineCache : public ScriptFunction

+ 6 - 0
lib/Runtime/Library/WebAssemblyInstance.h

@@ -4,11 +4,16 @@
 //-------------------------------------------------------------------------------------------------------
 
 #pragma once
+#ifdef ENABLE_WASM
 
 namespace Js
 {
     class WebAssemblyInstance : public DynamicObject
     {
+    protected:
+        DEFINE_VTABLE_CTOR(WebAssemblyInstance, DynamicObject);
+        DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(WebAssemblyInstance);
+
     public:
         class EntryInfo
         {
@@ -40,3 +45,4 @@ namespace Js
     };
 
 } // namespace Js
+#endif

+ 22 - 18
lib/Runtime/Library/WebAssemblyModule.cpp

@@ -23,7 +23,6 @@ WebAssemblyModule::WebAssemblyModule(Js::ScriptContext* scriptContext, const byt
     m_memoryMaxSize(0),
     m_tableInitSize(0),
     m_tableMaxSize(0),
-    m_alloc(_u("WebAssemblyModule"), scriptContext->GetThreadContext()->GetPageAllocator(), Js::Throw::OutOfMemory),
     m_indirectfuncs(nullptr),
     m_exports(nullptr),
     m_exportCount(0),
@@ -37,12 +36,13 @@ WebAssemblyModule::WebAssemblyModule(Js::ScriptContext* scriptContext, const byt
     m_binaryBufferLength(binaryBufferLength),
     m_customSections(nullptr)
 {
+    m_alloc = HeapNew(ArenaAllocator, _u("WebAssemblyModule"), scriptContext->GetThreadContext()->GetPageAllocator(), Js::Throw::OutOfMemory);
     //the first elm is the number of Vars in front of I32; makes for a nicer offset computation
     memset(m_globalCounts, 0, sizeof(uint) * Wasm::WasmTypes::Limit);
     m_functionsInfo = RecyclerNew(scriptContext->GetRecycler(), WasmFunctionInfosList, scriptContext->GetRecycler());
-    m_imports = Anew(&m_alloc, WasmImportsList, &m_alloc);
-    m_globals = Anew(&m_alloc, WasmGlobalsList, &m_alloc);
-    m_reader = Anew(&m_alloc, Wasm::WasmBinaryReader, &m_alloc, this, binaryBuffer, binaryBufferLength);
+    m_imports = Anew(m_alloc, WasmImportsList, m_alloc);
+    m_globals = Anew(m_alloc, WasmGlobalsList, m_alloc);
+    m_reader = Anew(m_alloc, Wasm::WasmBinaryReader, m_alloc, this, binaryBuffer, binaryBufferLength);
 }
 
 /* static */
@@ -436,7 +436,7 @@ WebAssemblyModule::AddWasmFunctionInfo(Wasm::WasmSignature* sig)
 {
     uint32 functionId = GetWasmFunctionCount();
     // must be recycler memory, since it holds reference to the function body
-    Wasm::WasmFunctionInfo* funcInfo = RecyclerNew(GetRecycler(), Wasm::WasmFunctionInfo, &m_alloc, sig, functionId);
+    Wasm::WasmFunctionInfo* funcInfo = RecyclerNew(GetRecycler(), Wasm::WasmFunctionInfo, m_alloc, sig, functionId);
     m_functionsInfo->Add(funcInfo);
     return funcInfo;
 }
@@ -472,7 +472,7 @@ WebAssemblyModule::AttachCustomInOutTracingReader(Wasm::WasmFunctionInfo* func,
         throw Wasm::WasmCompilationException(_u("InOut tracing reader signature mismatch"));
     }
     // Create the custom reader to generate the import thunk
-    Wasm::WasmCustomReader* customReader = Anew(&m_alloc, Wasm::WasmCustomReader, &m_alloc);
+    Wasm::WasmCustomReader* customReader = Anew(m_alloc, Wasm::WasmCustomReader, m_alloc);
     // Print the function name we are calling
     {
         Wasm::WasmNode nameNode;
@@ -551,7 +551,7 @@ WebAssemblyModule::AttachCustomInOutTracingReader(Wasm::WasmFunctionInfo* func,
 void
 WebAssemblyModule::AllocateFunctionExports(uint32 entries)
 {
-    m_exports = AnewArrayZ(&m_alloc, Wasm::WasmExport, entries);
+    m_exports = AnewArrayZ(m_alloc, Wasm::WasmExport, entries);
     m_exportCount = entries;
 }
 
@@ -589,7 +589,7 @@ WebAssemblyModule::AddFunctionImport(uint32 sigId, const char16* modName, uint32
     }
 
     // Store the information about the import
-    Wasm::WasmImport* importInfo = Anew(&m_alloc, Wasm::WasmImport);
+    Wasm::WasmImport* importInfo = Anew(m_alloc, Wasm::WasmImport);
     importInfo->kind = Wasm::ExternalKinds::Function;
     importInfo->modNameLen = modNameLen;
     importInfo->modName = modName;
@@ -600,7 +600,7 @@ WebAssemblyModule::AddFunctionImport(uint32 sigId, const char16* modName, uint32
     Wasm::WasmSignature* signature = GetSignature(sigId);
     Wasm::WasmFunctionInfo* funcInfo = AddWasmFunctionInfo(signature);
     // Create the custom reader to generate the import thunk
-    Wasm::WasmCustomReader* customReader = Anew(&m_alloc, Wasm::WasmCustomReader, &m_alloc);
+    Wasm::WasmCustomReader* customReader = Anew(m_alloc, Wasm::WasmCustomReader, m_alloc);
     for (uint32 iParam = 0; iParam < (uint32)signature->GetParamCount(); iParam++)
     {
         Wasm::WasmNode node;
@@ -649,7 +649,7 @@ WebAssemblyModule::GetImport(uint32 i) const
 void
 WebAssemblyModule::AddGlobalImport(const char16* modName, uint32 modNameLen, const char16* importName, uint32 importNameLen)
 {
-    Wasm::WasmImport* wi = Anew(&m_alloc, Wasm::WasmImport);
+    Wasm::WasmImport* wi = Anew(m_alloc, Wasm::WasmImport);
     wi->kind = Wasm::ExternalKinds::Global;
     wi->importName = importName;
     wi->importNameLen = importNameLen;
@@ -661,7 +661,7 @@ WebAssemblyModule::AddGlobalImport(const char16* modName, uint32 modNameLen, con
 void
 WebAssemblyModule::AddMemoryImport(const char16* modName, uint32 modNameLen, const char16* importName, uint32 importNameLen)
 {
-    Wasm::WasmImport* wi = Anew(&m_alloc, Wasm::WasmImport);
+    Wasm::WasmImport* wi = Anew(m_alloc, Wasm::WasmImport);
     wi->kind = Wasm::ExternalKinds::Memory;
     wi->importName = importName;
     wi->importNameLen = importNameLen;
@@ -674,7 +674,7 @@ WebAssemblyModule::AddMemoryImport(const char16* modName, uint32 modNameLen, con
 void
 WebAssemblyModule::AddTableImport(const char16* modName, uint32 modNameLen, const char16* importName, uint32 importNameLen)
 {
-    Wasm::WasmImport* wi = Anew(&m_alloc, Wasm::WasmImport);
+    Wasm::WasmImport* wi = Anew(m_alloc, Wasm::WasmImport);
     wi->kind = Wasm::ExternalKinds::Table;
     wi->importName = importName;
     wi->importNameLen = importNameLen;
@@ -732,7 +732,7 @@ WebAssemblyModule::ValidateInitExportForOffset(const Wasm::WasmNode& initExpr) c
 void
 WebAssemblyModule::AddGlobal(Wasm::GlobalReferenceTypes::Type refType, Wasm::WasmTypes::WasmType type, bool isMutable, Wasm::WasmNode init)
 {
-    Wasm::WasmGlobal* global = Anew(&m_alloc, Wasm::WasmGlobal, refType, m_globalCounts[type]++, type, isMutable, init);
+    Wasm::WasmGlobal* global = Anew(m_alloc, Wasm::WasmGlobal, refType, m_globalCounts[type]++, type, isMutable, init);
     m_globals->Add(global);
 }
 
@@ -757,7 +757,7 @@ WebAssemblyModule::AllocateDataSegs(uint32 count)
 {
     Assert(count != 0);
     m_datasegCount = count;
-    m_datasegs = AnewArray(&m_alloc, Wasm::WasmDataSegment*, count);
+    m_datasegs = AnewArray(m_alloc, Wasm::WasmDataSegment*, count);
 }
 
 void
@@ -782,7 +782,7 @@ WebAssemblyModule::AllocateElementSegs(uint32 count)
 {
     Assert(count != 0);
     m_elementsegCount = count;
-    m_elementsegs = AnewArrayZ(&m_alloc, Wasm::WasmElementSegment*, count);
+    m_elementsegs = AnewArrayZ(m_alloc, Wasm::WasmElementSegment*, count);
 }
 
 void
@@ -842,13 +842,17 @@ WebAssemblyModule::GetModuleEnvironmentSize() const
 void
 WebAssemblyModule::Finalize(bool isShutdown)
 {
-    m_alloc.Clear();
+    if (m_alloc)
+    {
+        HeapDelete(m_alloc);
+        m_alloc = nullptr;
+    }
 }
 
 void
 WebAssemblyModule::Dispose(bool isShutdown)
 {
-    Assert(m_alloc.Size() == 0);
+    Assert(!m_alloc);
 }
 
 void
@@ -923,7 +927,7 @@ WebAssemblyModule::AddCustomSection(Wasm::CustomSection customSection)
 {
     if (!m_customSections)
     {
-        m_customSections = Anew(&m_alloc, CustomSectionsList, &m_alloc);
+        m_customSections = Anew(m_alloc, CustomSectionsList, m_alloc);
     }
     m_customSections->Add(customSection);
 }

+ 7 - 2
lib/Runtime/Library/WebAssemblyModule.h

@@ -2,9 +2,9 @@
 // Copyright (C) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
-
 #pragma once
 
+#ifdef ENABLE_WASM
 #include "../WasmReader/WasmParseTree.h"
 
 namespace Wasm
@@ -24,6 +24,10 @@ namespace Js
 {
 class WebAssemblyModule : public DynamicObject
 {
+protected:
+    DEFINE_VTABLE_CTOR(WebAssemblyModule, DynamicObject);
+    DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(WebAssemblyModule);
+
 public:
 
     class EntryInfo
@@ -186,7 +190,8 @@ private:
 
     Field(uint32) m_startFuncIndex;
 
-    FieldNoBarrier(ArenaAllocator) m_alloc;
+    FieldNoBarrier(ArenaAllocator*) m_alloc;
 };
 
 } // namespace Js
+#endif

+ 0 - 1
test/wasm/debugger.js.dbg.baseline

@@ -1 +0,0 @@
-[]

BIN
test/wasm/debugger.wasm


+ 0 - 20
test/wasm/debugger.wast

@@ -1,20 +0,0 @@
-;;-------------------------------------------------------------------------------------------------------
-;; Copyright (C) Microsoft. All rights reserved.
-;; Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
-;;-------------------------------------------------------------------------------------------------------
-(module
-    (import "test" "foo" (func $foo (param i32)))
-    (func (export "a") (param i32)
-        (call $foo (get_local 0))
-    )
-    (func $b (export "b") (param i32)
-        (call $foo (get_local 0))
-    )
-
-    (func $c (export "c") (param i32)
-        (call $d (get_local 0))
-    )
-    (func $d (param i32)
-        (call $b (get_local 0))
-    )
-)

+ 46 - 18
test/wasm/debugger.js → test/wasm/debugger_basic.js

@@ -5,30 +5,57 @@
 
 const realPrint = print;
 WScript.Echo = print = console.log = () => {};
-if (WScript.Arguments.indexOf("-v") !== -1) {
+if (WScript.Arguments.indexOf("--verbose") !== -1) {
   WScript.Echo = print = console.log = realPrint;
 }
-
+let isAttached = WScript.Arguments.indexOf("debuglaunch") !== -1;
 function attach() {
+  if (isAttached) return Promise.resolve();
   return new Promise(r => WScript.Attach(() => {
+    isAttached = true;
     print("attached");
     r();
   }));
 }
 function detach() {
+  if (!isAttached) return Promise.resolve();
   return new Promise(r => WScript.Detach(() => {
+    isAttached = false;
     print("detached");
     r();
   }));
 }
-const buf = readbuffer("debugger.wasm");
-const {exports: {a, b, c}} = new WebAssembly.Instance(new WebAssembly.Module(buf), {test: {
-  foo: function(val) {
-    print(val);
-    // causes exception
-    return val.b.c;
-  }
-}});
+const buf = WebAssembly.wabt.convertWast2Wasm(`(module
+  (import "test" "mem" (memory 1))
+  (import "test" "table" (table 15 anyfunc))
+  (import "test" "foo" (func $foo (param i32)))
+  (func (export "a") (param i32)
+    (call $foo (get_local 0))
+  )
+  (func $b (export "b") (param i32)
+    (call $foo (get_local 0))
+  )
+
+  (func $c (export "c") (param i32)
+    (call $d (get_local 0))
+  )
+  (func $d (param i32)
+    (call $b (get_local 0))
+  )
+)`);
+function makeInstance(foo) {
+  const mem = new WebAssembly.Memory({initial: 1});
+  const table = new WebAssembly.Table({initial: 15, element: "anyfunc"});
+  const module = new WebAssembly.Module(buf);
+  const instance = new WebAssembly.Instance(module, {test: {mem, table, foo}});
+  debugger;
+  return instance;
+}
+const {exports: {a, b, c}} = makeInstance(val => {
+  print(val);
+  // causes exception
+  return val.b.c;
+});
 
 let id = 0;
 function runTest(fn) {
@@ -43,6 +70,7 @@ function caught(e) {
 }
 
 function runA() {
+  debugger;
   try {runTest(a);} catch (e) {caught(e);}
 }
 function runB() {
@@ -64,7 +92,7 @@ attach()
   .then(runB)
   .then(() => {
     let p = Promise.resolve();
-    for(let i = 0; i < 20; ++i) {
+    for (let i = 0; i < 20; ++i) {
       p = p
         .then(attach)
         .then(runB)
@@ -76,23 +104,23 @@ attach()
     return p;
   })
   .then(() => {
-    for(let i = 0; i < 20; ++i) {
+    for (let i = 0; i < 20; ++i) {
       runC();
     }
   })
   .then(attach)
   .then(() => {
-    for(let i = 0; i < 20; ++i) {
+    for (let i = 0; i < 20; ++i) {
       runC();
     }
   })
   .then(() => {
     let testValue = 0;
-    const {exports: {c: newC}} = new WebAssembly.Instance(new WebAssembly.Module(buf), {test: {
-      foo: function(val) {
-        testValue = val;
-      }
-    }});
+    const {exports: {c: newC}} = makeInstance(val => {
+      debugger;
+      testValue = val;
+    });
+    debugger;
     newC(15);
     if (testValue !== 15) {
       realPrint("Invalid assignment through import under debugger");

+ 95 - 0
test/wasm/debugger_basic.js.dbg.baseline

@@ -0,0 +1,95 @@
+[
+  {
+    "breakpoints": []
+  },
+  {
+    "this": "Object {...}",
+    "arguments": "Object {...}"
+  },
+  {
+    "callStack": [
+      {
+        "line": 72,
+        "column": 2,
+        "sourceText": "debugger",
+        "function": "runA"
+      }
+    ]
+  },
+  {
+    "breakpoints": []
+  },
+  {
+    "this": "Object {...}",
+    "arguments": "Object {...}",
+    "locals": {
+      "mem": "WebAssembly.Memory {...}",
+      "table": "WebAssembly.Table {...}",
+      "module": "WebAssembly.Module {...}",
+      "instance": "WebAssembly.Instance {...}",
+      "foo": "function <large string>"
+    }
+  },
+  {
+    "callStack": [
+      {
+        "line": 50,
+        "column": 2,
+        "sourceText": "debugger",
+        "function": "makeInstance"
+      },
+      {
+        "line": 118,
+        "column": 4,
+        "sourceText": "const {exports: {c: newC}} = makeInstance(val => {\r\n      debugger;\r\n      testValue = val;\r\n    })",
+        "function": "Anonymous function"
+      }
+    ]
+  },
+  {
+    "breakpoints": []
+  },
+  {
+    "arguments": "Object {...}",
+    "locals": {
+      "newC": "function <large string>",
+      "testValue": "number 0"
+    }
+  },
+  {
+    "callStack": [
+      {
+        "line": 122,
+        "column": 4,
+        "sourceText": "debugger",
+        "function": "Anonymous function"
+      }
+    ]
+  },
+  {
+    "breakpoints": []
+  },
+  {
+    "arguments": "Object {...}",
+    "locals": {
+      "val": "number 15"
+    },
+    "scopes0": "undefined undefined"
+  },
+  {
+    "callStack": [
+      {
+        "line": 119,
+        "column": 6,
+        "sourceText": "debugger",
+        "function": "Anonymous function"
+      },
+      {
+        "line": 123,
+        "column": 4,
+        "sourceText": "newC(15)",
+        "function": "Anonymous function"
+      }
+    ]
+  }
+]

+ 125 - 0
test/wasm/debugger_basic_launch.js.dbg.baseline

@@ -0,0 +1,125 @@
+[
+  {
+    "breakpoints": []
+  },
+  {
+    "this": "Object {...}",
+    "arguments": "Object {...}",
+    "locals": {
+      "mem": "WebAssembly.Memory {...}",
+      "table": "WebAssembly.Table {...}",
+      "module": "WebAssembly.Module {...}",
+      "instance": "WebAssembly.Instance {...}",
+      "foo": "function <large string>"
+    }
+  },
+  {
+    "callStack": [
+      {
+        "line": 50,
+        "column": 2,
+        "sourceText": "debugger",
+        "function": "makeInstance"
+      },
+      {
+        "line": 53,
+        "column": 0,
+        "sourceText": "const {exports: {a, b, c}} = makeInstance(val => {\r\n  print(val);\r\n  // causes exception\r\n  return val.b.c;\r\n})",
+        "function": "Global code"
+      }
+    ]
+  },
+  {
+    "breakpoints": []
+  },
+  {
+    "this": "Object {...}",
+    "arguments": "Object {...}"
+  },
+  {
+    "callStack": [
+      {
+        "line": 72,
+        "column": 2,
+        "sourceText": "debugger",
+        "function": "runA"
+      }
+    ]
+  },
+  {
+    "breakpoints": []
+  },
+  {
+    "this": "Object {...}",
+    "arguments": "Object {...}",
+    "locals": {
+      "mem": "WebAssembly.Memory {...}",
+      "table": "WebAssembly.Table {...}",
+      "module": "WebAssembly.Module {...}",
+      "instance": "WebAssembly.Instance {...}",
+      "foo": "function <large string>"
+    }
+  },
+  {
+    "callStack": [
+      {
+        "line": 50,
+        "column": 2,
+        "sourceText": "debugger",
+        "function": "makeInstance"
+      },
+      {
+        "line": 118,
+        "column": 4,
+        "sourceText": "const {exports: {c: newC}} = makeInstance(val => {\r\n      debugger;\r\n      testValue = val;\r\n    })",
+        "function": "Anonymous function"
+      }
+    ]
+  },
+  {
+    "breakpoints": []
+  },
+  {
+    "arguments": "Object {...}",
+    "locals": {
+      "newC": "function <large string>",
+      "testValue": "number 0"
+    }
+  },
+  {
+    "callStack": [
+      {
+        "line": 122,
+        "column": 4,
+        "sourceText": "debugger",
+        "function": "Anonymous function"
+      }
+    ]
+  },
+  {
+    "breakpoints": []
+  },
+  {
+    "arguments": "Object {...}",
+    "locals": {
+      "val": "number 15"
+    },
+    "scopes0": "undefined undefined"
+  },
+  {
+    "callStack": [
+      {
+        "line": 119,
+        "column": 6,
+        "sourceText": "debugger",
+        "function": "Anonymous function"
+      },
+      {
+        "line": 123,
+        "column": 4,
+        "sourceText": "newC(15)",
+        "function": "Anonymous function"
+      }
+    ]
+  }
+]

+ 28 - 21
test/wasm/rlexe.xml

@@ -166,27 +166,34 @@
     <tags>exclude_jshost,exclude_win7,exclude_dynapogo,exclude_xplat</tags>
   </default>
 </test>
-<test>
-  <default>
-    <files>debugger.js</files>
-    <compile-flags>-wasm -dbgbaseline:debugger.js.dbg.baseline</compile-flags>
-    <tags>exclude_serialized,exclude_jshost,exclude_snap,require_debugger,exclude_xplat</tags>
-  </default>
-</test>
-<test>
-  <default>
-    <files>debugger.js</files>
-    <compile-flags>-wasm -maic:1 -dbgbaseline:debugger.js.dbg.baseline</compile-flags>
-    <tags>exclude_serialized,exclude_jshost,exclude_snap,require_debugger,exclude_xplat</tags>
-  </default>
-</test>
-<test>
-  <default>
-    <files>wasmcctx.js</files>
-    <compile-flags>-wasm -dbgbaseline:wasmcctx.js.dbg.baseline</compile-flags>
-    <tags>exclude_serialized,exclude_jshost,exclude_snap,require_debugger,exclude_xplat</tags>
-  </default>
-</test>
+  <test>
+    <default>
+      <files>debugger_basic.js</files>
+      <compile-flags>-wasm -dbgbaseline:debugger_basic.js.dbg.baseline</compile-flags>
+      <tags>exclude_jshost,exclude_win7,exclude_snap,require_debugger,exclude_xplat</tags>
+    </default>
+  </test>
+  <test>
+    <default>
+      <files>debugger_basic.js</files>
+      <compile-flags>-wasm -maic:1 -dbgbaseline:debugger_basic.js.dbg.baseline</compile-flags>
+      <tags>exclude_jshost,exclude_win7,exclude_snap,require_debugger,exclude_xplat</tags>
+    </default>
+  </test>
+  <test>
+    <default>
+      <files>debugger_basic.js</files>
+      <compile-flags>-wasm -debuglaunch -args debuglaunch -endargs -dbgbaseline:debugger_basic_launch.js.dbg.baseline</compile-flags>
+      <tags>exclude_jshost,exclude_win7,exclude_snap,require_debugger,exclude_xplat</tags>
+    </default>
+  </test>
+  <test>
+    <default>
+      <files>wasmcctx.js</files>
+      <compile-flags>-wasm -dbgbaseline:wasmcctx.js.dbg.baseline -InspectMaxStringLength:50</compile-flags>
+      <tags>exclude_jshost,exclude_win7,exclude_snap,require_debugger,exclude_xplat</tags>
+    </default>
+  </test>
 <test>
   <default>
     <files>oom_wasm.js</files>

+ 25 - 1
test/wasm/wasmcctx.js

@@ -18,9 +18,33 @@ const ccx = WScript.LoadScriptFile("wasmcctxmodule.js", "samethread");
 let exports;
 function createModule() {
   exports = ccx.createModule();
+  const {mem, table, lastModule, lastInstance} = ccx;
+  /**bp:locals();bp:evaluate('String(lastInstance)');bp:evaluate('String(lastModule)');bp:evaluate('String(mem)');bp:evaluate('String(table)')**/
 }
+
+let id = 0;
+function runTest(fn) {
+  try {
+    //debugger;
+    fn(++id|0);
+  } catch (e) {
+    if (!(e instanceof (ccx.MyExceptionExport))) {
+      print(`Unexpected error: ${e.stack}`);
+    }
+  } finally {
+    if (ccx.testValue !== id) {
+      print(`Expected ${ccx.testValue} to be ${id}`);
+    }
+  }
+}
+
+function runTests({a, c}) {
+  runTest(a);
+  runTest(c);
+}
+
 function run() {
-  ccx.runTests(exports);
+  runTests(exports);
 }
 
 createModule();

+ 62 - 1
test/wasm/wasmcctx.js.dbg.baseline

@@ -1 +1,62 @@
-[]
+[
+  {
+    "this": "Object {...}",
+    "arguments": "Object {...}",
+    "locals": {
+      "mem": "WebAssembly.Memory {...}",
+      "table": "WebAssembly.Table {...}",
+      "lastModule": "WebAssembly.Module {...}",
+      "lastInstance": "WebAssembly.Instance {...}"
+    }
+  },
+  {
+    "evaluate": {
+      "String(lastInstance)": "string [object WebAssembly.Instance]"
+    }
+  },
+  {
+    "evaluate": {
+      "String(lastModule)": "string [object WebAssembly.Module]"
+    }
+  },
+  {
+    "evaluate": {
+      "String(mem)": "string [object WebAssembly.Memory]"
+    }
+  },
+  {
+    "evaluate": {
+      "String(table)": "string [object WebAssembly.Table]"
+    }
+  },
+  {
+    "this": "Object {...}",
+    "arguments": "Object {...}",
+    "locals": {
+      "mem": "WebAssembly.Memory {...}",
+      "table": "WebAssembly.Table {...}",
+      "lastModule": "WebAssembly.Module {...}",
+      "lastInstance": "WebAssembly.Instance {...}"
+    }
+  },
+  {
+    "evaluate": {
+      "String(lastInstance)": "string [object WebAssembly.Instance]"
+    }
+  },
+  {
+    "evaluate": {
+      "String(lastModule)": "string [object WebAssembly.Module]"
+    }
+  },
+  {
+    "evaluate": {
+      "String(mem)": "string [object WebAssembly.Memory]"
+    }
+  },
+  {
+    "evaluate": {
+      "String(table)": "string [object WebAssembly.Table]"
+    }
+  }
+]

+ 24 - 27
test/wasm/wasmcctxmodule.js

@@ -3,36 +3,33 @@
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
-const buf = readbuffer("debugger.wasm");
-let testValue;
+const buf = WebAssembly.wabt.convertWast2Wasm(`(module
+  (import "test" "foo" (func $foo (param i32)))
+  (func $a (export "a") (param i32)
+    (call $foo (get_local 0))
+  )
+  (func $c (export "c") (param i32)
+    (call $d (get_local 0))
+  )
+  (func $d (param i32)
+    (call $a (get_local 0))
+  )
+)`);
+var testValue;
+class MyException extends Error {}
+var MyExceptionExport = MyException;
+var lastModule;
+var lastInstance;
+var mem = new WebAssembly.Memory({initial: 1});
+var table = new WebAssembly.Table({element: "anyfunc", initial: 15});
+
 function createModule() {
-  const {exports} = new WebAssembly.Instance(new WebAssembly.Module(buf), {test: {
+  lastModule = new WebAssembly.Module(buf);
+  lastInstance = new WebAssembly.Instance(lastModule, {test: {
     foo: function(val) {
       testValue = val;
-      // causes exception
-      return val.b.c;
+      throw new MyException();
     }
   }});
-  return exports;
-}
-
-let id = 0;
-function runTest(fn) {
-  try {
-    fn(++id|0);
-  } catch (e) {
-    if (!(e instanceof TypeError)) {
-      print(`Unexpected error: ${e.stack}`);
-    }
-  } finally {
-    if (testValue !== id) {
-      print(`Expected ${testValue} to be ${id}`);
-    }
-  }
-}
-
-function runTests({a, b, c}) {
-  runTest(a);
-  runTest(b);
-  runTest(c);
+  return lastInstance.exports;
 }