Relax URI matching in V8 Wasm frame regex (#161)

Handle URIs other than `wasm://`.

Fixes #131.
diff --git a/lib/src/frame.dart b/lib/src/frame.dart
index bd0a582..d4043b7 100644
--- a/lib/src/frame.dart
+++ b/lib/src/frame.dart
@@ -48,7 +48,7 @@
 // To avoid having multiple groups for the same part of the frame, this regex
 // matches unmatched parentheses after the member name.
 final _v8WasmFrame = RegExp(r'^\s*at (?:(?<member>.+) )?'
-    r'(?:\(?(?:(?<uri>wasm:\S+):wasm-function\[(?<index>\d+)\]'
+    r'(?:\(?(?:(?<uri>\S+):wasm-function\[(?<index>\d+)\]'
     r'\:0x(?<offset>[0-9a-fA-F]+))\)?)$');
 
 // eval as function (https://example.com/stuff.dart.js:560:28), efn:3:28
diff --git a/test/frame_test.dart b/test/frame_test.dart
index e62e843..a5dfc20 100644
--- a/test/frame_test.dart
+++ b/test/frame_test.dart
@@ -651,6 +651,15 @@
     expect(frame.member, 'main tear-off trampoline');
   });
 
+  test('parses a V8 Wasm frame with a name with colons and parens', () {
+    var frame = Frame.parseV8('   at a::b::c() '
+        '(https://a.b.com/x/y/z.wasm:wasm-function[66334]:0x12c28ad)');
+    expect(frame.uri, Uri.parse('https://a.b.com/x/y/z.wasm'));
+    expect(frame.line, 1);
+    expect(frame.column, 0x12c28ad + 1);
+    expect(frame.member, 'a::b::c()');
+  });
+
   test('parses a V8 Wasm frame without a name', () {
     var frame =
         Frame.parseV8('    at wasm://wasm/0006d966:wasm-function[119]:0xbb13');