Skip to content

Commit

Permalink
Upgrade to Glimmer VM 0.37.0
Browse files Browse the repository at this point in the history
The only API change in this version of the VM relates to TypeScript types for the DOM. Type signatures now use SimpleDOM types throughout, helping ensure code doesn’t inadvertently rely on DOM APIs that are not available in SSR mode.

The other change has to do with what happens when an exception is thrown during render. Currently, Glimmer has a limited capacity to recover the state of the VM when errors are thrown from an opcode. A quick-and-dirty fix has been applied to Ember to try to catch and recover from these states, but options are limited until the root issue is addressed in Glimmer VM.

This commit changes a previously passing test to be skipped. This is because the old test covered behavior that only worked in some limited scenarios, because it left the DOM in a bad state. This could lead to cases where the same DOM element would be rendered multiple times, or in the wrong location. Glimmer VM 0.37.0 does more rigorous type checking and now fails when a re-render is attempted and the DOM is left in a bad state.

After a discussion between myself, @chancancode, @krisselden and @wycats, we felt that it was okay to temporarily mark this test as skipped since the behavior it captures was not working consistently anyway. We plan to address this more robustly in the VM itself, at which time we can re-enable the test, and remove some of the more ad hoc error recovery semantics from Ember itself.
  • Loading branch information
tomdale committed Dec 4, 2018
1 parent e329e3f commit bc7dbcf
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 118 deletions.
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@
"resolve": "^1.6.0"
},
"devDependencies": {
"@glimmer/compiler": "^0.36.4",
"@glimmer/compiler": "^0.37.0",
"@glimmer/env": "^0.1.7",
"@glimmer/interfaces": "^0.36.4",
"@glimmer/node": "^0.36.4",
"@glimmer/opcode-compiler": "^0.36.4",
"@glimmer/program": "^0.36.4",
"@glimmer/reference": "^0.36.4",
"@glimmer/runtime": "^0.36.4",
"@glimmer/interfaces": "^0.37.0",
"@glimmer/node": "^0.37.0",
"@glimmer/opcode-compiler": "^0.37.0",
"@glimmer/program": "^0.37.0",
"@glimmer/reference": "^0.37.0",
"@glimmer/runtime": "^0.37.0",
"@types/qunit": "^2.5.0",
"@types/rsvp": "^4.0.1",
"amd-name-resolver": "^1.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ export default class CurlyComponentManager

didCreateElement(
{ component, classRef, environment }: ComponentStateBucket,
element: HTMLElement,
element: Simple.Element,
operations: ElementOperations
): void {
setViewElement(component, element);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { OwnedTemplateMeta } from '@ember/-internals/views';
import { _instrumentStart } from '@ember/instrumentation';
import { assign } from '@ember/polyfills';
import { DEBUG } from '@glimmer/env';
import { ComponentCapabilities, Option, Unique } from '@glimmer/interfaces';
import { ComponentCapabilities, Option, Simple, Unique } from '@glimmer/interfaces';
import { CONSTANT_TAG, Tag, VersionedPathReference } from '@glimmer/reference';
import {
Arguments,
Expand Down Expand Up @@ -164,7 +164,7 @@ export function createRootOutlet(outletView: OutletView): OutletComponentDefinit

didCreateElement(
component: OutletInstanceState,
element: Element,
element: Simple.Element,
_operations: ElementOperations
): void {
// to add GUID id and class
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/-internals/glimmer/lib/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ const Component = CoreView.extend(
*/
readDOMAttr(name: string) {
// TODO revisit this
let element = getViewElement(this) as HTMLElement;
let element = getViewElement(this);
let isSVG = element.namespaceURI === SVG_NAMESPACE;
let { type, normalized } = normalizeProperty(element, name);

Expand Down
4 changes: 2 additions & 2 deletions packages/@ember/-internals/glimmer/lib/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { OWNER, Owner } from '@ember/-internals/owner';
import { constructStyleDeprecationMessage, lookupComponent } from '@ember/-internals/views';
import { warn } from '@ember/debug';
import { DEBUG } from '@glimmer/env';
import { Option } from '@glimmer/interfaces';
import { Option, Simple } from '@glimmer/interfaces';
import { OpaqueIterable, VersionedReference } from '@glimmer/reference';
import {
ElementBuilder,
Expand Down Expand Up @@ -143,7 +143,7 @@ if (DEBUG) {
element,
attribute: string,
isTrusting: boolean,
namespace: Option<string>
namespace: Option<Simple.AttrNamespace>
) {
if (attribute === 'style' && !isTrusting) {
return new StyleAttributeManager({ element, name: attribute, namespace });
Expand Down
8 changes: 4 additions & 4 deletions packages/@ember/-internals/glimmer/lib/modifiers/custom.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Factory } from '@ember/-internals/owner';
import { Opaque } from '@glimmer/interfaces';
import { Opaque, Simple } from '@glimmer/interfaces';
import { Tag } from '@glimmer/reference';
import { Arguments, CapturedArguments, ModifierManager } from '@glimmer/runtime';
import { ManagerArgs, valueForCapturedArgs } from '../utils/managers';
Expand Down Expand Up @@ -35,7 +35,7 @@ export class CustomModifierDefinition<ModifierInstance> {

export class CustomModifierState<ModifierInstance> {
constructor(
public element: Element,
public element: Simple.Element,
public delegate: ModifierManagerDelegate<ModifierInstance>,
public modifier: ModifierInstance,
public args: CapturedArguments
Expand All @@ -51,7 +51,7 @@ export class CustomModifierState<ModifierInstance> {
export interface ModifierManagerDelegate<ModifierInstance> {
capabilities: Capabilities;
createModifier(factory: Opaque, args: ManagerArgs): ModifierInstance;
installModifier(instance: ModifierInstance, element: Element, args: ManagerArgs): void;
installModifier(instance: ModifierInstance, element: Simple.Element, args: ManagerArgs): void;
updateModifier(instance: ModifierInstance, args: ManagerArgs): void;
destroyModifier(instance: ModifierInstance, args: ManagerArgs): void;
}
Expand Down Expand Up @@ -84,7 +84,7 @@ class CustomModifierManager<ModifierInstance>
CustomModifierDefinitionState<ModifierInstance>
> {
create(
element: Element,
element: Simple.Element,
definition: CustomModifierDefinitionState<ModifierInstance>,
args: Arguments
) {
Expand Down
5 changes: 3 additions & 2 deletions packages/@ember/-internals/glimmer/lib/setup-registry.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { hasDOM } from '@ember/-internals/browser-environment';
import { privatize as P, Registry } from '@ember/-internals/container';
import { ENV } from '@ember/-internals/environment';
import { Simple } from '@glimmer/interfaces';
import Component from './component';
import Checkbox from './components/checkbox';
import LinkToComponent from './components/link-to';
Expand Down Expand Up @@ -62,13 +63,13 @@ export function setupApplicationRegistry(registry: Registry) {
}

registry.register('service:-dom-changes', {
create({ document }: { document: HTMLDocument }) {
create({ document }: { document: Simple.Document }) {
return new DOMChanges(document);
},
});

registry.register('service:-dom-tree-construction', {
create({ document }: { document: HTMLDocument }) {
create({ document }: { document: Simple.Document }) {
let Implementation = hasDOM ? DOMTreeConstruction : NodeDOMTreeConstruction;
return new Implementation(document);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ moduleFor(
this.assertText('hello');
}

['@test it can recover resets the transaction when an error is thrown during rerender'](
['@skip it can recover resets the transaction when an error is thrown during rerender'](
assert
) {
let shouldThrow = false;
Expand Down
202 changes: 104 additions & 98 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,119 +2,125 @@
# yarn lockfile v1


"@glimmer/compiler@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.36.4.tgz#eee7ef4e49b2e7f8c59be8c0dda70b859333a810"
integrity sha512-3l3cRCucpm/+sO3c4Ulx7kOtrHL/I0KpsnBmbBaHuWpvxrSXWig8iFrYcxxxmzbwAARv2FlZjGn4ZzVK9CTK/w==
"@glimmer/compiler@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.37.0.tgz#861d9c8064b54c24895262e1dd6a805cf24b8175"
integrity sha512-h01QJvqzClYw6Y5+DptqaB74KeBz14fsbNlig2O1sH5B2RKXRXo6T/OFSlFO/BHdzPLIrhyrkNQ/pooy2nTNmQ==
dependencies:
"@glimmer/interfaces" "^0.36.4"
"@glimmer/syntax" "^0.36.4"
"@glimmer/util" "^0.36.4"
"@glimmer/wire-format" "^0.36.4"
"@glimmer/interfaces" "^0.37.0"
"@glimmer/syntax" "^0.37.0"
"@glimmer/util" "^0.37.0"
"@glimmer/wire-format" "^0.37.0"

"@glimmer/encoder@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.36.4.tgz#d635c674c28f248fa246ea10cae7a850f7d1528c"
integrity sha512-xGExG3l5WVsASMKNG5Id+lmZ3eFEYYbXlX8bzhg6qgW8KkRJFxG8FRTy5AS4mI83LM8ZZ+LActVCcID49D86/A==
"@glimmer/encoder@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.37.0.tgz#3689bb8dbdbce4ae45783b447d1a7fcc40c067c2"
integrity sha512-NS5UTeBZd0GRQYpUVQ/sSYriHxAPLSb4z1qlRzWQCfJmovtMRRYgcFpyRck/ckmFsXdlfDL+Nu0hJLOcYU+oXQ==

"@glimmer/env@^0.1.7":
version "0.1.7"
resolved "https://registry.yarnpkg.com/@glimmer/env/-/env-0.1.7.tgz#fd2d2b55a9029c6b37a6c935e8c8871ae70dfa07"
integrity sha1-/S0rVakCnGs3psk16MiHGucN+gc=

"@glimmer/interfaces@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.36.4.tgz#49dc81bd9aaf41905fe8426dc273f25cb339139c"
integrity sha512-WQiZvhYuO1QwpsKZfPyojAOS3TwhO3NoPfdjrRO5CcugSgx44f7BeIhMIQdlsTL1aRYtWA3bMDoIipXh8iiEOw==
dependencies:
"@glimmer/wire-format" "^0.36.4"

"@glimmer/low-level@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/low-level/-/low-level-0.36.4.tgz#3c09b2f8c81565b78f284b4d0404a41fdfc98997"
integrity sha512-muQOH6k5ApKhYSgiKSTDKBH71xgkG/kBBIXTAYe5a0JQ0S1hxfxYkJrRjGpIuNk3jRq+aczaYLy3MP4aTJJioQ==

"@glimmer/node@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.36.4.tgz#17f27fa63fbedbcbda0d46186f8318387886398e"
integrity sha512-spcpWUmT516GgZto8WpGrBXbFz0CETmpEFepXiZ2hRaNlwKFyWhOu8hvbx07DxncOMMEk5JXHUAjluVo/Zb6MQ==
dependencies:
"@glimmer/interfaces" "^0.36.4"
"@glimmer/runtime" "^0.36.4"
simple-dom "^0.3.0"

"@glimmer/opcode-compiler@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.36.4.tgz#b438313734ff2eb4748a3ab15a48a6b7ff56ef28"
integrity sha512-3cHgH2vx78fdahHQtGJ0RllIxtnGORSxEdMwUnOzl4aMd94V6oiIXg2PJJPKtcOfnZ5ufBvtWt/Hv1f9vtRuag==
dependencies:
"@glimmer/encoder" "^0.36.4"
"@glimmer/interfaces" "^0.36.4"
"@glimmer/program" "^0.36.4"
"@glimmer/reference" "^0.36.4"
"@glimmer/util" "^0.36.4"
"@glimmer/vm" "^0.36.4"
"@glimmer/wire-format" "^0.36.4"

"@glimmer/program@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.36.4.tgz#6c3eb97268400eea4e3940c62cac28435d9c17de"
integrity sha512-nxVb7B1g+9vA3mo5M0RNJxjRNU/2buLHkzfcCwuK2RR5B+xUvlBQVbi/AB8CvNrIAw11X3yv64x6i7/8he3T/w==
dependencies:
"@glimmer/encoder" "^0.36.4"
"@glimmer/interfaces" "^0.36.4"
"@glimmer/util" "^0.36.4"

"@glimmer/reference@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.36.4.tgz#e8651eb825b26875b52079c42ed0070b1a5f3776"
integrity sha512-W2xjZ+9JI7wKgXQnxBW9Gapx1ZvvCiBK1NFkzUIhn6wQuMhZIbhuRS8Z6t2k69ial58L+XL2U3Yc+zgr77yNHw==
dependencies:
"@glimmer/util" "^0.36.4"

"@glimmer/runtime@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.36.4.tgz#ae9eeef0b2a5b62b366bc030279b446af7de2090"
integrity sha512-ig3wvGfrZdoRt/x2qSj1MRntJLC0qTU6svg4gy6aom7yUH0xUxEiMUaTzKIiBmDtzj9MYbVIZUO/ZDI6LiUKiA==
dependencies:
"@glimmer/interfaces" "^0.36.4"
"@glimmer/low-level" "^0.36.4"
"@glimmer/program" "^0.36.4"
"@glimmer/reference" "^0.36.4"
"@glimmer/util" "^0.36.4"
"@glimmer/vm" "^0.36.4"
"@glimmer/wire-format" "^0.36.4"

"@glimmer/syntax@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.36.4.tgz#dfc5d1f0e2bdbc8ff8ec482357311748776aa2ff"
integrity sha512-F/KPqEnpU4IdaYb7vDevyMDTCuKsgqcxhBdFauysUj7ZSwa1BljHxFoUbCsTLVxdpQGU1QTr6NNiD8Ihn4XUjA==
dependencies:
"@glimmer/interfaces" "^0.36.4"
"@glimmer/util" "^0.36.4"
"@glimmer/interfaces@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.37.0.tgz#7e16dc3b44369ea084e13064dd30ec14ed86623f"
integrity sha512-tLvn6O0SqPotkQy/I/PBgnUorho+kim7psitpAZQMljOY8ocSf0+dfIY4GKQsTqefbpHbmdu4dYBhyy09xDJag==
dependencies:
"@glimmer/wire-format" "^0.37.0"
"@simple-dom/interface" "1.4.0"

"@glimmer/low-level@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/low-level/-/low-level-0.37.0.tgz#ef49a49abb829c5ffcf539c3408cc545df688875"
integrity sha512-OFPE0KVUbSsQhpJpwI2zmG+1+y0NkpSJzn4qQ1kuKzpk50TABeTBo8ycqJFTgYh/cjus/W212G2YgEN/YXZqZw==

"@glimmer/node@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.37.0.tgz#cbf51153ec3d3e858314b95f249c8c80f458fa23"
integrity sha512-f2F/ttR1J3pkOLBGEuR/I+Z4tNKLuii5983LnUB6UDW0DKbz3DZwkejVcYr6wxhaU5QuD5RWl+AkaREOfZuh7w==
dependencies:
"@glimmer/interfaces" "^0.37.0"
"@glimmer/runtime" "^0.37.0"

"@glimmer/opcode-compiler@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.37.0.tgz#26b37cc3a569ba88377e373d602f518b65b36cc3"
integrity sha512-a+wMGHXTnzrvapFzyxx7tE73msnnIFCDy7O5vH/gnwNqy8VEGeXperJDpwZxxn0SnSVtwvCPJ+85MXFDmcfrvQ==
dependencies:
"@glimmer/encoder" "^0.37.0"
"@glimmer/interfaces" "^0.37.0"
"@glimmer/program" "^0.37.0"
"@glimmer/reference" "^0.37.0"
"@glimmer/util" "^0.37.0"
"@glimmer/vm" "^0.37.0"
"@glimmer/wire-format" "^0.37.0"

"@glimmer/program@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.37.0.tgz#25aaa78363216a47074246c4ddea0d6241e3295b"
integrity sha512-wsu9R5+ytndMJg4AXBGm8dJax3q/vk5PkSxl8VHi5jxje4Ja/8AjJl7SpE2nRCfmLpq8rV6vHSmZaKY1tSRANQ==
dependencies:
"@glimmer/encoder" "^0.37.0"
"@glimmer/interfaces" "^0.37.0"
"@glimmer/util" "^0.37.0"

"@glimmer/reference@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.37.0.tgz#5910810d932a03f5bb62014caa9733cecf0683ed"
integrity sha512-NCYlu9X0ok7pJiGb/Uevv/84xA1Z49PHDUcDrN0X/bDzSI/zoFy//wPevjPO/+ihBtD5Hy9Ve3eC/lfSSWsWVA==
dependencies:
"@glimmer/util" "^0.37.0"

"@glimmer/runtime@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.37.0.tgz#b1ec8303f6a97141310bb4fe3ecac7396311381a"
integrity sha512-U9FKj4id2HwA1FTVJLFWpCIsICOaIZklwhTHHd7XrtoETdFaesn7/4e3fH/LNx0BrPkXy6dfD/9I7izLFM4ToQ==
dependencies:
"@glimmer/interfaces" "^0.37.0"
"@glimmer/low-level" "^0.37.0"
"@glimmer/program" "^0.37.0"
"@glimmer/reference" "^0.37.0"
"@glimmer/util" "^0.37.0"
"@glimmer/vm" "^0.37.0"
"@glimmer/wire-format" "^0.37.0"
"@simple-dom/interface" "^1.4.0"

"@glimmer/syntax@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.37.0.tgz#3d91aef9ecad70e70654584f84552c195f3280a6"
integrity sha512-DTWPjTK6f7sXAYIqLjC7lfNpONyY21jmHjhzAbC6nbEfZ3DegmogWDBLCO8dhun1bAF4T2FL7+gLho698UqBiw==
dependencies:
"@glimmer/interfaces" "^0.37.0"
"@glimmer/util" "^0.37.0"
handlebars "^4.0.6"
simple-html-tokenizer "^0.5.6"

"@glimmer/util@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.36.4.tgz#a79287fe261cc5b198d1c35943dc8aa879b98bc5"
integrity sha512-ng907Cr4i5NsgmP6Im7KzbK5EfP9M21PZoacrhzIhljFW8XptExH0Sekhx8XJkb4SRt+b28cq4X29WM3EFidOQ==
"@glimmer/util@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.37.0.tgz#962937c187b05a8a371d5b064674e74e838411c7"
integrity sha512-gwApoQ4xAAPKUBd9IpKYqW3UojZv45gIH+hxi9G9BbZWQZd1f9qIUHwk6JP+bNQ4zvxv9z4QEL1pOCWLx0TE3w==

"@glimmer/vm@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.36.4.tgz#0ed6cead77b02488a8ad9187d1b64b7cf0c706ce"
integrity sha512-1V7F8ZjScgchScb7Q42VAJLHRM7wZvjqwX7sUEZJWPlZsf5Zu6U88/695U4fPLyiQkYdyBkeIQs+HTklYy7r6g==
"@glimmer/vm@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.37.0.tgz#34268bb46a69e551379ccc554773e80900461c24"
integrity sha512-1H0Vag7kgZKJ6hCFg9Lv5OA0Q5b130atdnbKb79AS0OUpT3G7f64h/eCIlxMxhF+YhRi2nrD5Hb5bVuuD8Pszg==
dependencies:
"@glimmer/interfaces" "^0.36.4"
"@glimmer/program" "^0.36.4"
"@glimmer/util" "^0.36.4"
"@glimmer/interfaces" "^0.37.0"
"@glimmer/program" "^0.37.0"
"@glimmer/util" "^0.37.0"

"@glimmer/wire-format@^0.36.4":
version "0.36.4"
resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.36.4.tgz#520918fbd2d4a91953081476ddcc269b0c714795"
integrity sha512-Chwwu77kQios2HWb8vGcuMi35iT3GHfwCyqQZa/BniZyN0MYkg/uT5UMDQwSiW5ZFZxGteHjds50397x/WnG4Q==
"@glimmer/wire-format@^0.37.0":
version "0.37.0"
resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.37.0.tgz#cd26f3d260d92a9e5d2873bd0234b54556ab3e85"
integrity sha512-wMBCo9cosxKzcsHuPlFzd+WHS8AqJoNYYK+LcpgLZRhjXO55oeirEQcwthV1uHdYs0CK7i+HcljuMDdJk2heww==
dependencies:
"@glimmer/util" "^0.36.4"
"@glimmer/util" "^0.37.0"

"@simple-dom/[email protected]", "@simple-dom/interface@^1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@simple-dom/interface/-/interface-1.4.0.tgz#e8feea579232017f89b0138e2726facda6fbb71f"
integrity sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA==

"@types/acorn@^4.0.3":
version "4.0.3"
Expand Down

0 comments on commit bc7dbcf

Please sign in to comment.