Version 2.10.0-86.0.dev

Merge commit 'c9182ad3c00c802af5fba20283801a4cdaf38614' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index c3ba326..12e1c33 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2020-08-18T11:26:08.472483",
+  "generated": "2020-08-18T15:38:52.410101",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -719,7 +719,7 @@
       "name": "wasm",
       "rootUri": "../pkg/wasm",
       "packageUri": "lib/",
-      "languageVersion": "2.6"
+      "languageVersion": "2.10"
     },
     {
       "name": "watcher",
diff --git a/DEPS b/DEPS
index f84b666..a31cd21 100644
--- a/DEPS
+++ b/DEPS
@@ -220,7 +220,7 @@
   Var("dart_root") + "/third_party/d8": {
       "packages": [{
           "package": "dart/d8",
-          "version": "version:7.8.279",
+          "version": "version:8.5.210",
       }],
       "dep_type": "cipd",
   },
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_null_aware_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_null_aware_test.dart
index 032264e..ed938e6 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_null_aware_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_null_aware_test.dart
@@ -20,18 +20,16 @@
 
   Future<void> test_singleFile() async {
     await resolveTestUnit('''
-abstract class A {
-  int m();
+class A {
+  int m(int p) => p;
 }
-int f(A a) => null == a ? null : a.m();
-int g(A a) => a == null ? null : a.m();
+int f(A x, A y) => x == null ? null : x.m(y == null ? null : y.m(0));
 ''');
     await assertHasFix('''
-abstract class A {
-  int m();
+class A {
+  int m(int p) => p;
 }
-int f(A a) => a?.m();
-int g(A a) => a?.m();
+int f(A x, A y) => x?.m(y?.m(0));
 ''');
   }
 }
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 8f199a4..7353b55 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 0.40.2
+* Require `meta: ^1.2.3`.
+
 ## 0.40.1
 * Added `LocalVariableElement.hasInitializer`,
   `PropertyInducingElement.hasInitializer`, `ParameterElement.hasDefaultValue`.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 1204ae1..0cff7cf 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.40.1
+version: 0.40.2
 description: This package provides a library that performs static analysis of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
 
@@ -15,7 +15,7 @@
   convert: ^2.0.0
   crypto: ^2.0.0
   glob: ^1.0.3
-  meta: ^1.0.2
+  meta: ^1.2.3
   package_config: ^1.0.0
   path: ^1.0.0
   pub_semver: ^1.4.2
diff --git a/pkg/wasm/lib/module.dart b/pkg/wasm/lib/module.dart
deleted file mode 100644
index 4b9cde4..0000000
--- a/pkg/wasm/lib/module.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'runtime.dart';
-import 'dart:typed_data';
-import 'dart:ffi';
-
-class WasmModule {
-  Pointer<WasmerModule> _module;
-
-  WasmModule(Uint8List data) {
-    _module = WasmRuntime().compile(data);
-  }
-}
diff --git a/pkg/wasm/lib/runtime.dart b/pkg/wasm/lib/runtime.dart
deleted file mode 100644
index f26689c..0000000
--- a/pkg/wasm/lib/runtime.dart
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:ffi';
-import 'dart:io';
-import 'dart:typed_data';
-import 'package:ffi/ffi.dart';
-import 'package:path/path.dart' as path;
-
-const int WasmerResultOk = 1;
-const int WasmerResultError = 2;
-
-const int WasmerValueTagI32 = 0;
-const int WasmerValueTagI64 = 1;
-const int WasmerValueTagF32 = 2;
-const int WasmerValueTagF64 = 3;
-
-class WasmerModule extends Struct {}
-
-typedef NativeWasmerCompileFn = Uint32 Function(
-    Pointer<Pointer<WasmerModule>>, Pointer<Uint8>, Uint32);
-typedef WasmerCompileFn = int Function(
-    Pointer<Pointer<WasmerModule>>, Pointer<Uint8>, int);
-
-class WasmRuntime {
-  static WasmRuntime _inst;
-
-  DynamicLibrary _lib;
-  WasmerCompileFn _compile;
-
-  factory WasmRuntime() {
-    if (_inst == null) {
-      _inst = WasmRuntime._init();
-    }
-    return _inst;
-  }
-
-  static String _getLibName() {
-    if (Platform.isMacOS) return "libwasmer.dylib";
-    if (Platform.isLinux) return "libwasmer.so";
-    throw Exception("Wasm not currently supported on this platform");
-  }
-
-  static String _getLibDir() {
-    // The common case, and how cli_util.dart computes the Dart SDK directory,
-    // path.dirname called twice on Platform.resolvedExecutable.
-    var commonLibDir = path.join(
-        path.absolute(path.dirname(path.dirname(Platform.resolvedExecutable))),
-        'bin',
-        'third_party',
-        'wasmer');
-    if (Directory(commonLibDir).existsSync()) {
-      return commonLibDir;
-    }
-
-    // This is the less common case where the user is in the checked out Dart
-    // SDK, and is executing dart via:
-    // ./out/ReleaseX64/dart ...
-    var checkedOutLibDir = path.join(
-        path.absolute(path.dirname(Platform.resolvedExecutable)),
-        'dart-sdk',
-        'bin',
-        'third_party',
-        'wasmer');
-    if (Directory(checkedOutLibDir).existsSync()) {
-      return checkedOutLibDir;
-    }
-
-    // If neither returned above, we return the common case:
-    return commonLibDir;
-  }
-
-  WasmRuntime._init() {
-    var libPath = path.join(_getLibDir(), _getLibName());
-    _lib = DynamicLibrary.open(libPath);
-    _compile = _lib
-        .lookup<NativeFunction<NativeWasmerCompileFn>>('wasmer_compile')
-        .asFunction();
-  }
-
-  Pointer<WasmerModule> compile(Uint8List data) {
-    var dataPtr = allocate<Uint8>(count: data.length);
-    for (int i = 0; i < data.length; ++i) {
-      dataPtr[i] = data[i];
-    }
-
-    var modulePtrPtr = allocate<Pointer<WasmerModule>>();
-    int result = _compile(modulePtrPtr, dataPtr, data.length);
-    Pointer<WasmerModule> modulePtr = modulePtrPtr.value;
-
-    free(modulePtrPtr);
-    free(dataPtr);
-
-    if (result != WasmerResultOk) {
-      throw Exception("Wasm module compile failed");
-    }
-
-    return modulePtr;
-  }
-}
diff --git a/pkg/wasm/lib/src/function.dart b/pkg/wasm/lib/src/function.dart
new file mode 100644
index 0000000..c5840bf
--- /dev/null
+++ b/pkg/wasm/lib/src/function.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'runtime.dart';
+import 'wasmer_api.dart';
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+/// WasmFunction is a callable function from a WasmInstance.
+class WasmFunction {
+  Pointer<WasmerExportFunc> _func;
+  List<int> _argTypes;
+  int _returnType;
+  Pointer<WasmerValue> _args;
+  Pointer<WasmerValue> _result;
+
+  WasmFunction(this._func, this._argTypes, this._returnType) {
+    _args = allocate<WasmerValue>(count: _argTypes.length);
+    _result = allocate<WasmerValue>();
+    for (var i = 0; i < _argTypes.length; ++i) {
+      _args[i].tag = _argTypes[i];
+    }
+  }
+
+  bool _fillArg(dynamic arg, int i) {
+    switch (_argTypes[i]) {
+      case WasmerValueTagI32:
+        if (arg is! int) return false;
+        _args[i].i32 = arg;
+        return true;
+      case WasmerValueTagI64:
+        if (arg is! int) return false;
+        _args[i].i64 = arg;
+        return true;
+      case WasmerValueTagF32:
+        if (arg is! num) return false;
+        _args[i].f32 = arg;
+        return true;
+      case WasmerValueTagF64:
+        if (arg is! num) return false;
+        _args[i].f64 = arg;
+        return true;
+    }
+  }
+
+  dynamic apply(List<dynamic> args) {
+    if (args.length != _argTypes.length) {
+      throw Exception("Wrong number arguments for WASM function");
+    }
+    for (var i = 0; i < args.length; ++i) {
+      if (!_fillArg(args[i], i)) {
+        throw Exception("Bad argument type for WASM function");
+      }
+    }
+    WasmRuntime().call(_func, _args, _argTypes.length, _result,
+        _returnType == WasmerValueTagVoid ? 0 : 1);
+
+    if (_returnType == WasmerValueTagVoid) {
+      return null;
+    }
+    assert(_returnType == _result.ref.tag);
+    switch (_returnType) {
+      case WasmerValueTagI32:
+        return _result.ref.i32;
+      case WasmerValueTagI64:
+        return _result.ref.i64;
+      case WasmerValueTagF32:
+        return _result.ref.f32;
+      case WasmerValueTagF64:
+        return _result.ref.f64;
+    }
+  }
+
+  dynamic noSuchMethod(Invocation invocation) {
+    if (invocation.memberName == #call) {
+      return apply(invocation.positionalArguments);
+    }
+    return super.noSuchMethod(invocation);
+  }
+}
diff --git a/pkg/wasm/lib/src/module.dart b/pkg/wasm/lib/src/module.dart
new file mode 100644
index 0000000..1034a9e
--- /dev/null
+++ b/pkg/wasm/lib/src/module.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'runtime.dart';
+import 'function.dart';
+import 'wasmer_api.dart';
+import 'dart:typed_data';
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+/// WasmModule is a compiled module that can be instantiated.
+class WasmModule {
+  Pointer<WasmerModule> _module;
+
+  /// Compile a module.
+  WasmModule(Uint8List data) {
+    _module = WasmRuntime().compile(data);
+  }
+
+  /// Instantiate the module with the given imports.
+  WasmInstance instantiate(WasmImports imports) {
+    return WasmInstance(_module, imports);
+  }
+}
+
+/// WasmImports holds all the imports for a WasmInstance.
+class WasmImports {
+  Pointer<WasmerImport> _imports;
+  int _capacity;
+  int _length;
+
+  /// Create an imports object.
+  WasmImports([this._capacity = 4]) : _length = 0 {
+    _imports = allocate<WasmerImport>(count: this._capacity);
+  }
+
+  /// Returns the number of imports.
+  int get length => _length;
+}
+
+/// WasmInstance is an instantiated WasmModule.
+class WasmInstance {
+  Pointer<WasmerModule> _module;
+  Pointer<WasmerInstance> _instance;
+  List<WasmFunction> _functions;
+
+  WasmInstance(this._module, WasmImports imports) {
+    var runtime = WasmRuntime();
+    _instance = runtime.instantiate(_module, imports._imports, imports.length);
+    _functions = [];
+    var exps = runtime.exports(_instance);
+    for (var e in exps) {
+      var kind = runtime.exportKind(e);
+      if (kind == WasmerImpExpKindFunction) {
+        var f = runtime.exportToFunction(e);
+        _functions.add(
+            WasmFunction(f, runtime.getArgTypes(f), runtime.getReturnType(f)));
+      }
+    }
+  }
+
+  List<dynamic> get functions => _functions;
+}
diff --git a/pkg/wasm/lib/src/runtime.dart b/pkg/wasm/lib/src/runtime.dart
new file mode 100644
index 0000000..b8d3686
--- /dev/null
+++ b/pkg/wasm/lib/src/runtime.dart
@@ -0,0 +1,219 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'dart:ffi';
+import 'dart:io';
+import 'dart:typed_data';
+import 'package:ffi/ffi.dart';
+import 'package:path/path.dart' as path;
+import 'wasmer_api.dart';
+
+class WasmRuntime {
+  static WasmRuntime _inst;
+
+  DynamicLibrary _lib;
+  WasmerCompileFn _compile;
+  WasmerInstantiateFn _instantiate;
+  WasmerInstanceExportsFn _instance_exports;
+  WasmerExportsLenFn _exports_len;
+  WasmerExportsGetFn _exports_get;
+  WasmerExportKindFn _export_kind;
+  WasmerExportToFuncFn _export_to_func;
+  WasmerExportFuncReturnsArityFn _export_func_returns_arity;
+  WasmerExportFuncReturnsFn _export_func_returns;
+  WasmerExportFuncParamsArityFn _export_func_params_arity;
+  WasmerExportFuncParamsFn _export_func_params;
+  WasmerExportFuncCallFn _export_func_call;
+
+  factory WasmRuntime() {
+    if (_inst == null) {
+      _inst = WasmRuntime._init();
+    }
+    return _inst;
+  }
+
+  static String _getLibName() {
+    if (Platform.isMacOS) return "libwasmer.dylib";
+    if (Platform.isLinux) return "libwasmer.so";
+    throw Exception("Wasm not currently supported on this platform");
+  }
+
+  static String _getLibDir() {
+    // The common case, and how cli_util.dart computes the Dart SDK directory,
+    // path.dirname called twice on Platform.resolvedExecutable.
+    var commonLibDir = path.join(
+        path.absolute(path.dirname(path.dirname(Platform.resolvedExecutable))),
+        'bin',
+        'third_party',
+        'wasmer');
+    if (Directory(commonLibDir).existsSync()) {
+      return commonLibDir;
+    }
+
+    // This is the less common case where the user is in the checked out Dart
+    // SDK, and is executing dart via:
+    // ./out/ReleaseX64/dart ...
+    var checkedOutLibDir = path.join(
+        path.absolute(path.dirname(Platform.resolvedExecutable)),
+        'dart-sdk',
+        'bin',
+        'third_party',
+        'wasmer');
+    if (Directory(checkedOutLibDir).existsSync()) {
+      return checkedOutLibDir;
+    }
+
+    // If neither returned above, we return the common case:
+    return commonLibDir;
+  }
+
+  WasmRuntime._init() {
+    var libPath = path.join(_getLibDir(), _getLibName());
+    _lib = DynamicLibrary.open(libPath);
+    _compile = _lib.lookupFunction<NativeWasmerCompileFn, WasmerCompileFn>(
+        'wasmer_compile');
+    _instantiate =
+        _lib.lookupFunction<NativeWasmerInstantiateFn, WasmerInstantiateFn>(
+            'wasmer_module_instantiate');
+    _instance_exports = _lib.lookupFunction<NativeWasmerInstanceExportsFn,
+        WasmerInstanceExportsFn>('wasmer_instance_exports');
+    _exports_len =
+        _lib.lookupFunction<NativeWasmerExportsLenFn, WasmerExportsLenFn>(
+            'wasmer_exports_len');
+    _exports_get =
+        _lib.lookupFunction<NativeWasmerExportsGetFn, WasmerExportsGetFn>(
+            'wasmer_exports_get');
+    _export_kind =
+        _lib.lookupFunction<NativeWasmerExportKindFn, WasmerExportKindFn>(
+            'wasmer_export_kind');
+    _export_to_func =
+        _lib.lookupFunction<NativeWasmerExportToFuncFn, WasmerExportToFuncFn>(
+            'wasmer_export_to_func');
+    _export_func_returns_arity = _lib.lookupFunction<
+        NativeWasmerExportFuncReturnsArityFn,
+        WasmerExportFuncReturnsArityFn>('wasmer_export_func_returns_arity');
+    _export_func_returns = _lib.lookupFunction<NativeWasmerExportFuncReturnsFn,
+        WasmerExportFuncReturnsFn>('wasmer_export_func_returns');
+    _export_func_params_arity = _lib.lookupFunction<
+        NativeWasmerExportFuncParamsArityFn,
+        WasmerExportFuncParamsArityFn>('wasmer_export_func_params_arity');
+    _export_func_params = _lib.lookupFunction<NativeWasmerExportFuncParamsFn,
+        WasmerExportFuncParamsFn>('wasmer_export_func_params');
+    _export_func_call = _lib.lookupFunction<NativeWasmerExportFuncCallFn,
+        WasmerExportFuncCallFn>('wasmer_export_func_call');
+  }
+
+  Pointer<WasmerModule> compile(Uint8List data) {
+    var dataPtr = allocate<Uint8>(count: data.length);
+    for (int i = 0; i < data.length; ++i) {
+      dataPtr[i] = data[i];
+    }
+
+    var modulePtrPtr = allocate<Pointer<WasmerModule>>();
+    int result = _compile(modulePtrPtr, dataPtr, data.length);
+    Pointer<WasmerModule> modulePtr = modulePtrPtr.value;
+
+    free(modulePtrPtr);
+    free(dataPtr);
+
+    if (result != WasmerResultOk) {
+      throw Exception("Wasm module compile failed");
+    }
+
+    return modulePtr;
+  }
+
+  Pointer<WasmerInstance> instantiate(Pointer<WasmerModule> module,
+      Pointer<WasmerImport> imports, int numImports) {
+    var instancePtrPtr = allocate<Pointer<WasmerInstance>>();
+    int result = _instantiate(module, instancePtrPtr, imports, numImports);
+    Pointer<WasmerInstance> instancePtr = instancePtrPtr.value;
+    free(instancePtrPtr);
+
+    if (result != WasmerResultOk) {
+      throw Exception("Wasm module instantiation failed");
+    }
+
+    return instancePtr;
+  }
+
+  List<Pointer<WasmerExport>> exports(Pointer<WasmerInstance> instancePtr) {
+    var exportsPtrPtr = allocate<Pointer<WasmerExports>>();
+    _instance_exports(instancePtr, exportsPtrPtr);
+    Pointer<WasmerExports> exportsPtr = exportsPtrPtr.value;
+    free(exportsPtrPtr);
+
+    var n = _exports_len(exportsPtr);
+    var exps = <Pointer<WasmerExport>>[];
+    for (var i = 0; i < n; ++i) {
+      exps.add(_exports_get(exportsPtr, i));
+    }
+    return exps;
+  }
+
+  int exportKind(Pointer<WasmerExport> export) {
+    return _export_kind(export);
+  }
+
+  Pointer<WasmerExportFunc> exportToFunction(Pointer<WasmerExport> export) {
+    return _export_to_func(export);
+  }
+
+  List<int> getArgTypes(Pointer<WasmerExportFunc> func) {
+    var types = <int>[];
+    var nPtr = allocate<Uint32>();
+    var result = _export_func_params_arity(func, nPtr);
+    if (result != WasmerResultOk) {
+      free(nPtr);
+      throw Exception("Failed to get number of WASM function args");
+    }
+    var n = nPtr.value;
+    free(nPtr);
+    var argsPtr = allocate<Uint32>(count: n);
+    result = _export_func_params(func, argsPtr, n);
+    if (result != WasmerResultOk) {
+      free(argsPtr);
+      throw Exception("Failed to get WASM function args");
+    }
+    for (var i = 0; i < n; ++i) {
+      types.add(argsPtr[i]);
+    }
+    free(argsPtr);
+    return types;
+  }
+
+  int getReturnType(Pointer<WasmerExportFunc> func) {
+    var nPtr = allocate<Uint32>();
+    var result = _export_func_returns_arity(func, nPtr);
+    if (result != WasmerResultOk) {
+      free(nPtr);
+      throw Exception("Failed to get number of WASM function returns");
+    }
+    var n = nPtr.value;
+    free(nPtr);
+    if (n == 0) {
+      return WasmerValueTagVoid;
+    } else if (n > 1) {
+      throw Exception("Multiple return values are not supported");
+    }
+    var returnsPtr = allocate<Uint32>();
+    result = _export_func_params(func, returnsPtr, 1);
+    if (result != WasmerResultOk) {
+      free(returnsPtr);
+      throw Exception("Failed to get WASM function args");
+    }
+    var type = returnsPtr.value;
+    free(returnsPtr);
+    return type;
+  }
+
+  void call(Pointer<WasmerExportFunc> func, Pointer<WasmerValue> args,
+      int numArgs, Pointer<WasmerValue> results, int numResults) {
+    var result = _export_func_call(func, args, numArgs, results, numArgs);
+    if (result != WasmerResultOk) {
+      throw Exception("Failed to call WASM function");
+    }
+  }
+}
diff --git a/pkg/wasm/lib/src/wasmer_api.dart b/pkg/wasm/lib/src/wasmer_api.dart
new file mode 100644
index 0000000..dc5df74
--- /dev/null
+++ b/pkg/wasm/lib/src/wasmer_api.dart
@@ -0,0 +1,180 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'dart:typed_data';
+
+// wasmer_result_t
+const int WasmerResultOk = 1;
+const int WasmerResultError = 2;
+
+// wasmer_value_tag
+const int WasmerValueTagI32 = 0;
+const int WasmerValueTagI64 = 1;
+const int WasmerValueTagF32 = 2;
+const int WasmerValueTagF64 = 3;
+// The void tag is not part of the C API. It's used to represent the return type
+// of a void function.
+const int WasmerValueTagVoid = -1;
+
+// wasmer_import_export_kind
+const int WasmerImpExpKindFunction = 0;
+const int WasmerImpExpKindGlobal = 1;
+const int WasmerImpExpKindMemory = 2;
+const int WasmerImpExpKindTable = 3;
+
+// wasmer_module_t
+class WasmerModule extends Struct {}
+
+// wasmer_instance_t
+class WasmerInstance extends Struct {}
+
+// wasmer_exports_t
+class WasmerExports extends Struct {}
+
+// wasmer_export_t
+class WasmerExport extends Struct {}
+
+// wasmer_export_func_t
+class WasmerExportFunc extends Struct {}
+
+// wasmer_import_t
+class WasmerImport extends Struct {
+  Pointer<Uint8> module_name;
+
+  @Uint32()
+  int module_name_length;
+
+  Pointer<Uint8> import_name;
+
+  @Uint32()
+  int import_name_length;
+
+  // wasmer_import_export_kind
+  @Uint32()
+  int tag;
+
+  // wasmer_import_export_value, which is a union of wasmer_import_func_t*,
+  // wasmer_table_t*, wasmer_memory_t*, and wasmer_global_t*. The tag determines
+  // which type it is.
+  Pointer<Void> value;
+}
+
+// wasmer_byte_array
+class WasmerByteArray extends Struct {
+  Pointer<Uint8> bytes;
+
+  @Uint32()
+  int length;
+
+  Uint8List get list => bytes.asTypedList(length);
+}
+
+// wasmer_value_t
+class WasmerValue extends Struct {
+  // wasmer_value_tag
+  @Uint32()
+  int tag;
+
+  // wasmer_value, which is a union of int32_t, int64_t, float, and double. The
+  // tag determines which type it is. It's declared as an int64_t because that's
+  // large enough to hold all the types. We use ByteData to get the other types.
+  @Int64()
+  int value;
+
+  int get _off32 => Endian.host == Endian.little ? 0 : 4;
+  int get i64 => value;
+  ByteData get _getterBytes => ByteData(8)..setInt64(0, value, Endian.host);
+  int get i32 => _getterBytes.getInt32(_off32, Endian.host);
+  double get f32 => _getterBytes.getFloat32(_off32, Endian.host);
+  double get f64 => _getterBytes.getFloat64(0, Endian.host);
+
+  set i64(int val) => value = val;
+  set _val(ByteData bytes) => value = bytes.getInt64(0, Endian.host);
+  set i32(int val) => _val = ByteData(8)..setInt32(_off32, val, Endian.host);
+  set f32(num val) => _val = ByteData(8)..setFloat32(_off32, val, Endian.host);
+  set f64(num val) => _val = ByteData(8)..setFloat64(0, val, Endian.host);
+
+  bool get isI32 => tag == WasmerValueTagI32;
+  bool get isI64 => tag == WasmerValueTagI64;
+  bool get isF32 => tag == WasmerValueTagF32;
+  bool get isF64 => tag == WasmerValueTagF64;
+}
+
+// wasmer_compile
+typedef NativeWasmerCompileFn = Uint32 Function(
+    Pointer<Pointer<WasmerModule>>, Pointer<Uint8>, Uint32);
+typedef WasmerCompileFn = int Function(
+    Pointer<Pointer<WasmerModule>>, Pointer<Uint8>, int);
+
+// wasmer_module_instantiate
+typedef NativeWasmerInstantiateFn = Uint32 Function(Pointer<WasmerModule>,
+    Pointer<Pointer<WasmerInstance>>, Pointer<WasmerImport>, Int32);
+typedef WasmerInstantiateFn = int Function(Pointer<WasmerModule>,
+    Pointer<Pointer<WasmerInstance>>, Pointer<WasmerImport>, int);
+
+// wasmer_instance_exports
+typedef NativeWasmerInstanceExportsFn = Void Function(
+    Pointer<WasmerInstance>, Pointer<Pointer<WasmerExports>>);
+typedef WasmerInstanceExportsFn = void Function(
+    Pointer<WasmerInstance>, Pointer<Pointer<WasmerExports>>);
+
+// wasmer_exports_len
+typedef NativeWasmerExportsLenFn = Int32 Function(Pointer<WasmerExports>);
+typedef WasmerExportsLenFn = int Function(Pointer<WasmerExports>);
+
+// wasmer_exports_get
+typedef NativeWasmerExportsGetFn = Pointer<WasmerExport> Function(
+    Pointer<WasmerExports>, Int32);
+typedef WasmerExportsGetFn = Pointer<WasmerExport> Function(
+    Pointer<WasmerExports>, int);
+
+// wasmer_export_name
+typedef NativeWasmerExportNameFn = WasmerByteArray Function(
+    Pointer<WasmerExport>);
+typedef WasmerExportNameFn = WasmerByteArray Function(Pointer<WasmerExport>);
+
+// wasmer_export_kind
+typedef NativeWasmerExportKindFn = Uint32 Function(Pointer<WasmerExport>);
+typedef WasmerExportKindFn = int Function(Pointer<WasmerExport>);
+
+// wasmer_export_to_func
+typedef NativeWasmerExportToFuncFn = Pointer<WasmerExportFunc> Function(
+    Pointer<WasmerExport>);
+typedef WasmerExportToFuncFn = Pointer<WasmerExportFunc> Function(
+    Pointer<WasmerExport>);
+
+// wasmer_export_func_returns_arity
+typedef NativeWasmerExportFuncReturnsArityFn = Uint32 Function(
+    Pointer<WasmerExportFunc>, Pointer<Uint32>);
+typedef WasmerExportFuncReturnsArityFn = int Function(
+    Pointer<WasmerExportFunc>, Pointer<Uint32>);
+
+// wasmer_export_func_returns
+typedef NativeWasmerExportFuncReturnsFn = Uint32 Function(
+    Pointer<WasmerExportFunc>, Pointer<Uint32>, Uint32);
+typedef WasmerExportFuncReturnsFn = int Function(
+    Pointer<WasmerExportFunc>, Pointer<Uint32>, int);
+
+// wasmer_export_func_params_arity
+typedef NativeWasmerExportFuncParamsArityFn = Uint32 Function(
+    Pointer<WasmerExportFunc>, Pointer<Uint32>);
+typedef WasmerExportFuncParamsArityFn = int Function(
+    Pointer<WasmerExportFunc>, Pointer<Uint32>);
+
+// wasmer_export_func_params
+typedef NativeWasmerExportFuncParamsFn = Uint32 Function(
+    Pointer<WasmerExportFunc>, Pointer<Uint32>, Uint32);
+typedef WasmerExportFuncParamsFn = int Function(
+    Pointer<WasmerExportFunc>, Pointer<Uint32>, int);
+
+// wasmer_export_func_call
+typedef NativeWasmerExportFuncCallFn = Uint32 Function(
+    Pointer<WasmerExportFunc>,
+    Pointer<WasmerValue>,
+    Uint32,
+    Pointer<WasmerValue>,
+    Uint32);
+typedef WasmerExportFuncCallFn = int Function(Pointer<WasmerExportFunc>,
+    Pointer<WasmerValue>, int, Pointer<WasmerValue>, int);
diff --git a/pkg/wasm/lib/wasm.dart b/pkg/wasm/lib/wasm.dart
index 56b2f4b..877ff90 100644
--- a/pkg/wasm/lib/wasm.dart
+++ b/pkg/wasm/lib/wasm.dart
@@ -2,4 +2,5 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-export 'module.dart';
+export 'src/function.dart';
+export 'src/module.dart';
diff --git a/pkg/wasm/pubspec.yaml b/pkg/wasm/pubspec.yaml
index 04f9586..570631c 100644
--- a/pkg/wasm/pubspec.yaml
+++ b/pkg/wasm/pubspec.yaml
@@ -6,7 +6,7 @@
 # This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 environment:
-  sdk: ">=2.6.0"
+  sdk: '>=2.10.0-0 <2.10.0'
 dependencies:
   ffi: ^0.1.3
   path: ^1.0.0
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index a844493..6e0547b 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -15,13 +15,13 @@
 
 namespace dart {
 
-static const int8_t kDataBitsPerByte = 7;
-static const int8_t kByteMask = (1 << kDataBitsPerByte) - 1;
-static const int8_t kMaxUnsignedDataPerByte = kByteMask;
-static const int8_t kMinDataPerByte = -(1 << (kDataBitsPerByte - 1));
-static const int8_t kMaxDataPerByte = (~kMinDataPerByte & kByteMask);  // NOLINT
-static const uint8_t kEndByteMarker = (255 - kMaxDataPerByte);
-static const uint8_t kEndUnsignedByteMarker = (255 - kMaxUnsignedDataPerByte);
+// (S)LEB128 encodes 7 bits of data per byte (hence 128).
+static constexpr uint8_t kDataBitsPerByte = 7;
+static constexpr uint8_t kDataByteMask = (1 << kDataBitsPerByte) - 1;
+// If more data follows a given data byte, the high bit is set.
+static constexpr uint8_t kMoreDataMask = (1 << kDataBitsPerByte);
+// For SLEB128, the high bit in the data of the last byte is the sign bit.
+static constexpr uint8_t kSignMask = (1 << (kDataBitsPerByte - 1));
 
 typedef uint8_t* (*ReAlloc)(uint8_t* ptr, intptr_t old_size, intptr_t new_size);
 typedef void (*DeAlloc)(uint8_t* ptr);
@@ -50,19 +50,19 @@
   template <typename T>
   class Raw<2, T> {
    public:
-    static T Read(ReadStream* st) { return bit_cast<T>(st->Read16()); }
+    static T Read(ReadStream* st) { return bit_cast<T>(st->Read16<int16_t>()); }
   };
 
   template <typename T>
   class Raw<4, T> {
    public:
-    static T Read(ReadStream* st) { return bit_cast<T>(st->Read32()); }
+    static T Read(ReadStream* st) { return bit_cast<T>(st->Read32<int32_t>()); }
   };
 
   template <typename T>
   class Raw<8, T> {
    public:
-    static T Read(ReadStream* st) { return bit_cast<T>(st->Read64()); }
+    static T Read(ReadStream* st) { return bit_cast<T>(st->Read64<int64_t>()); }
   };
 
   // Reads 'len' bytes from the stream.
@@ -74,9 +74,15 @@
     current_ += len;
   }
 
+  // Reads a value of type [T] assuming an encoding of LEB128 (whether or not
+  // the type itself is unsigned).
   template <typename T = intptr_t>
   T ReadUnsigned() {
-    return Read<T>(kEndUnsignedByteMarker);
+    if (std::is_unsigned<T>::value) {
+      return ReadInternal<T>();
+    } else {
+      return bit_cast<T>(ReadUnsigned<typename std::make_unsigned<T>::type>());
+    }
   }
 
   intptr_t Position() const { return current_ - buffer_; }
@@ -103,9 +109,15 @@
     return (end_ - current_);
   }
 
+  // Reads a value of type [T] assuming an encoding of SLEB128 (whether or not
+  // the type itself is signed).
   template <typename T>
   T Read() {
-    return Read<T>(kEndByteMarker);
+    if (std::is_signed<T>::value) {
+      return ReadInternal<T>();
+    } else {
+      return bit_cast<T>(Read<typename std::make_signed<T>::type>());
+    }
   }
 
   uword ReadWordWith32BitReads() {
@@ -122,179 +134,112 @@
   }
 
  private:
-  uint16_t Read16() { return Read16(kEndByteMarker); }
-
-  uint32_t Read32() { return Read32(kEndByteMarker); }
-
-  uint64_t Read64() { return Read64(kEndByteMarker); }
-
   template <typename T>
-  T Read(uint8_t end_byte_marker) {
+  T ReadInternal() {
     using Unsigned = typename std::make_unsigned<T>::type;
     const uint8_t* c = current_;
-    ASSERT(c < end_);
-    Unsigned b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return b - end_byte_marker;
-    }
-    T r = 0;
+    Unsigned r = 0;
     uint8_t s = 0;
+    uint8_t b;
     do {
-      r |= static_cast<Unsigned>(b) << s;
-      s += kDataBitsPerByte;
       ASSERT(c < end_);
       b = *c++;
-    } while (b <= kMaxUnsignedDataPerByte);
+      r |= static_cast<Unsigned>(b & kDataByteMask) << s;
+      s += kDataBitsPerByte;
+    } while ((b & kMoreDataMask) != 0);
     current_ = c;
-    return r | (static_cast<Unsigned>(b - end_byte_marker) << s);
+    // At this point, [s] contains how many data bits have made it into the
+    // value. If the type is signed, the value negative, and the count of data
+    // bits is less than the size of the value, then we need to extend the sign
+    // by setting the remaining (unset) most significant bits (MSBs).
+    Unsigned sign_bits = 0;
+    const bool is_signed = std::is_signed<T>::value;
+    if (is_signed && (b & kSignMask) != 0 && s < (kBitsPerByte * sizeof(T))) {
+      // Create a bitmask for the current data bits and invert it.
+      sign_bits = ~((static_cast<Unsigned>(1) << s) - 1);
+    }
+    return static_cast<T>(r | sign_bits);
   }
 
-  uint16_t Read16(uint8_t end_byte_marker) {
-    const uint8_t* c = current_;
-    ASSERT(c < end_);
-    uint16_t b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return b - end_byte_marker;
-    }
-    uint16_t r = b;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint16_t>(b - end_byte_marker) << 7);
-    }
+// Setting up needed variables for the unrolled loop sections below.
+#define UNROLLED_INIT()                                                        \
+  using Unsigned = typename std::make_unsigned<T>::type;                       \
+  const uint8_t* c = current_;                                                 \
+  uint8_t b;                                                                   \
+  Unsigned r = 0;
 
-    r |= b << 7;
-    ASSERT(c < end_);
-    b = *c++;
-    ASSERT(b > kMaxUnsignedDataPerByte);
-    current_ = c;
-    return r | (static_cast<uint16_t>(b - end_byte_marker) << 14);
+// Part of the unrolled loop where the loop may stop, having read the last part,
+// or continue reading. If stopping, extend the sign for signed values.
+#define UNROLLED_BODY(bit_start)                                               \
+  static_assert(bit_start % kDataBitsPerByte == 0,                             \
+                "Bit start must be a multiple of the data bits per byte");     \
+  static_assert(bit_start >= 0 && bit_start < kBitsPerByte * sizeof(T),        \
+                "Starting unrolled body at invalid bit position");             \
+  ASSERT(c < end_);                                                            \
+  b = *c++;                                                                    \
+  r |= static_cast<Unsigned>(b & kDataByteMask) << bit_start;                  \
+  if ((b & kMoreDataMask) == 0) {                                              \
+    current_ = c;                                                              \
+    Unsigned sign_bits = 0;                                                    \
+    if (std::is_signed<T>::value && (b & kSignMask) != 0) {                    \
+      sign_bits = ~((static_cast<Unsigned>(1) << (bit_start + 7)) - 1);        \
+    }                                                                          \
+    return static_cast<T>(r | sign_bits);                                      \
   }
 
-  uint32_t Read32(uint8_t end_byte_marker) {
-    const uint8_t* c = current_;
-    ASSERT(c < end_);
-    uint32_t b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return b - end_byte_marker;
-    }
+// If the unrolled end is reached, the last part always includes the original
+// sign bit, so no need to sign extend.
+#define UNROLLED_END(bit_start)                                                \
+  static_assert(bit_start % kDataBitsPerByte == 0,                             \
+                "Bit start must be a multiple of the data bits per byte");     \
+  static_assert(bit_start >= 0 && bit_start < kBitsPerByte * sizeof(T),        \
+                "Starting unrolled end at invalid bit position");              \
+  static_assert(bit_start + kDataBitsPerByte >= kBitsPerByte * sizeof(T),      \
+                "Unrolled end does not contain final bits in value");          \
+  ASSERT(c < end_);                                                            \
+  b = *c++;                                                                    \
+  r |= static_cast<Unsigned>(b & kDataByteMask) << bit_start;                  \
+  ASSERT_EQUAL((b & kMoreDataMask), 0);                                        \
+  current_ = c;                                                                \
+  return static_cast<T>(r);
 
-    uint32_t r = b;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint32_t>(b - end_byte_marker) << 7);
-    }
-
-    r |= b << 7;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint32_t>(b - end_byte_marker) << 14);
-    }
-
-    r |= b << 14;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint32_t>(b - end_byte_marker) << 21);
-    }
-
-    r |= b << 21;
-    ASSERT(c < end_);
-    b = *c++;
-    ASSERT(b > kMaxUnsignedDataPerByte);
-    current_ = c;
-    return r | (static_cast<uint32_t>(b - end_byte_marker) << 28);
+  template <typename T>
+  T Read16() {
+    UNROLLED_INIT();
+    UNROLLED_BODY(0);
+    UNROLLED_BODY(7);
+    UNROLLED_END(14);
   }
 
-  uint64_t Read64(uint8_t end_byte_marker) {
-    const uint8_t* c = current_;
-    ASSERT(c < end_);
-    uint64_t b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return b - end_byte_marker;
-    }
-    uint64_t r = b;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 7);
-    }
-
-    r |= b << 7;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 14);
-    }
-
-    r |= b << 14;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 21);
-    }
-
-    r |= b << 21;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 28);
-    }
-
-    r |= b << 28;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 35);
-    }
-
-    r |= b << 35;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 42);
-    }
-
-    r |= b << 42;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 49);
-    }
-
-    r |= b << 49;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 56);
-    }
-
-    r |= b << 56;
-    ASSERT(c < end_);
-    b = *c++;
-    ASSERT(b > kMaxUnsignedDataPerByte);
-    current_ = c;
-    return r | (static_cast<uint64_t>(b - end_byte_marker) << 63);
+  template <typename T>
+  T Read32() {
+    UNROLLED_INIT();
+    UNROLLED_BODY(0);
+    UNROLLED_BODY(7);
+    UNROLLED_BODY(14);
+    UNROLLED_BODY(21);
+    UNROLLED_END(28);
   }
 
+  template <typename T>
+  T Read64() {
+    UNROLLED_INIT();
+    UNROLLED_BODY(0);
+    UNROLLED_BODY(7);
+    UNROLLED_BODY(14);
+    UNROLLED_BODY(21);
+    UNROLLED_BODY(28);
+    UNROLLED_BODY(35);
+    UNROLLED_BODY(42);
+    UNROLLED_BODY(49);
+    UNROLLED_BODY(56);
+    UNROLLED_END(63);
+  }
+
+#undef UNROLLED_END
+#undef UNROLLED_BODY
+#undef UNROLLED_INIT
+
   uint8_t ReadByte() {
     ASSERT(current_ < end_);
     return *current_++;
@@ -350,7 +295,7 @@
   class Raw<1, T> {
    public:
     static void Write(WriteStream* st, T value) {
-      st->WriteByte(bit_cast<int8_t>(value));
+      st->WriteByte(bit_cast<uint8_t>(value));
     }
   };
 
@@ -390,14 +335,17 @@
     }
   }
 
+  // Writes the LEB128 encoding of [value] to the stream (whether or not the
+  // type [T] is unsigned).
   template <typename T>
   void WriteUnsigned(T value) {
     ASSERT(value >= 0);
-    while (value > kMaxUnsignedDataPerByte) {
-      WriteByte(static_cast<uint8_t>(value & kByteMask));
-      value = value >> kDataBitsPerByte;
+    if (std::is_unsigned<T>::value) {
+      WriteInternal<T>(value);
+    } else {
+      using Unsigned = typename std::make_unsigned<T>::type;
+      WriteUnsigned<Unsigned>(bit_cast<Unsigned>(value));
     }
-    WriteByte(static_cast<uint8_t>(value + kEndUnsignedByteMarker));
   }
 
   void WriteBytes(const void* addr, intptr_t len) {
@@ -465,14 +413,16 @@
     current_ += len;  // Not len + 1 to swallow the terminating NUL.
   }
 
+  // Writes the SLEB128 encoding of [value] to the stream (whether or not the
+  // type [T] is signed).
   template <typename T>
   void Write(T value) {
-    T v = value;
-    while (v < kMinDataPerByte || v > kMaxDataPerByte) {
-      WriteByte(static_cast<uint8_t>(v & kByteMask));
-      v = v >> kDataBitsPerByte;
+    if (std::is_signed<T>::value) {
+      WriteInternal<T>(value);
+    } else {
+      using Signed = typename std::make_signed<T>::type;
+      Write<Signed>(bit_cast<Signed>(value));
     }
-    WriteByte(static_cast<uint8_t>(v + kEndByteMarker));
   }
 
   template <typename T>
@@ -487,6 +437,33 @@
   }
 
  private:
+  template <typename T>
+  void WriteInternal(T value) {
+    T remainder = value;
+    bool is_last_part;
+    do {
+      uint8_t part = static_cast<uint8_t>(remainder & kDataByteMask);
+      remainder >>= kDataBitsPerByte;
+      // For unsigned types, we're done when the remainder has no bits set.
+      // For signed types, we're done when either:
+      // - the remainder has no bits set and the part's sign bit is unset, or
+      // - the remainder has all bits set and the part's sign bit is set.
+      // If the remainder matches but the sign bit does not, we need one more
+      // part to set the sign bit correctly.
+      is_last_part =
+          std::is_unsigned<T>::value
+              ? remainder == static_cast<T>(0)
+              : (remainder == static_cast<T>(0) && (part & kSignMask) == 0) ||
+                    (remainder == ~static_cast<T>(0) &&
+                     (part & kSignMask) != 0);
+      if (!is_last_part) {
+        // Mark this part as having more parts following it.
+        part |= kMoreDataMask;
+      }
+      WriteByte(part);
+    } while (!is_last_part);
+  }
+
   DART_FORCE_INLINE void WriteByte(uint8_t value) {
     if (current_ >= end_) {
       Resize(1);
@@ -514,7 +491,6 @@
     ASSERT(end_ > *buffer_);
   }
 
- private:
   uint8_t** const buffer_;
   uint8_t* end_;
   uint8_t* current_;
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index 606ef61..cce2eac 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -962,35 +962,8 @@
         stream_(ASSERT_NOTNULL(stream)),
         address_map_(address_map) {}
 
-  void sleb128(intptr_t value) {
-    bool is_last_part = false;
-    while (!is_last_part) {
-      uint8_t part = value & 0x7F;
-      value >>= 7;
-      if ((value == 0 && (part & 0x40) == 0) ||
-          (value == static_cast<intptr_t>(-1) && (part & 0x40) != 0)) {
-        is_last_part = true;
-      } else {
-        part |= 0x80;
-      }
-      stream_->WriteFixed(part);
-    }
-  }
-
-  void uleb128(uintptr_t value) {
-    bool is_last_part = false;
-    while (!is_last_part) {
-      uint8_t part = value & 0x7F;
-      value >>= 7;
-      if (value == 0) {
-        is_last_part = true;
-      } else {
-        part |= 0x80;
-      }
-      stream_->WriteFixed(part);
-    }
-  }
-
+  void sleb128(intptr_t value) { stream_->Write(value); }
+  void uleb128(uintptr_t value) { stream_->WriteUnsigned(value); }
   void u1(uint8_t value) { stream_->WriteFixed(value); }
   // Can't use WriteFixed for these, as we may not be at aligned positions.
   void u2(uint16_t value) { stream_->WriteBytes(&value, sizeof(value)); }
diff --git a/tools/VERSION b/tools/VERSION
index 295e955..db91a19 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 85
+PRERELEASE 86
 PRERELEASE_PATCH 0
\ No newline at end of file