Skip to content
This repository has been archived by the owner on Oct 29, 2024. It is now read-only.

[FEAT] Modifier Managers #245

Merged
merged 1 commit into from
Mar 27, 2020
Merged

[FEAT] Modifier Managers #245

merged 1 commit into from
Mar 27, 2020

Conversation

pzuraq
Copy link
Member

@pzuraq pzuraq commented Mar 27, 2020

Adds modifier managers that match Ember's modifier manager API. They can
be defined by importing setModifierManager from @glimmer/core:

import {
  modifierCapabilities,
  setModifierManager,
} from '@glimmer/core';

Also allows users to use simple functions as modifiers:

function scroll(element, position) {
  element.scrollY = position;

  return () => element.scrollY = 0;
}

The function receives the element as the first argument, and any
positional arguments after that. It can return a destructor, which will
be called whenever the modifier is destroyed, or before it is updated
and the modifier is run again.

Also adds a TrackedObject implementation for tests, which makes life
for testing a bit easier.

Adds modifier managers that match Ember's modifier manager API. They can
be defined by importing `setModifierManager` from `@glimmer/core`:

```ts
import {
  modifierCapabilities,
  setModifierManager,
} from '@glimmer/core';
```

Also allows users to use simple functions as modifiers:

```js
function scroll(element, position) {
  element.scrollY = position;

  return () => element.scrollY = 0;
}
```

The function receives the element as the first argument, and any
positional arguments after that. It can return a destructor, which will
be called whenever the modifier is destroyed, or before it is updated
and the modifier is run again.

Also adds a `TrackedObject` implementation for tests, which makes life
for testing a bit easier.
Comment on lines +18 to +23
export {
ModifierManager,
ModifierDefinition,
capabilities as modifierCapabilities,
Capabilities as ModifierCapabilities,
} from './src/managers/modifier';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for not using export * 👯‍♂


if (delegate === undefined) {
if (DEBUG) {
assert(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, do these get stripped properly on their own or do they have to be within an if (DEBUG) {? Also, if they do have to be in an if (DEBUG) { what happens to the import?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the import should be tree-shaken, which is why I figured this pattern would be alright for now. We currently only replace DEBUG.

assert.strictEqual(
element.innerHTML,
await settled(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems somewhat surprising that settled returns the HTML

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the pattern established by the render() test helper. I agree, the more I work with it the more I think we need something a bit better. Ideally we would get QUnit.dom working in this repo, and allow render() to return the result (along with a way to destroy the result).

const element = document.getElementById('qunit-fixture')!;
const clickable = element.querySelector(selector)! as HTMLButtonElement;

clickable.click();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be using dispatch event here probably. Seems fine for now, it just reminds me that we really need to genericize the @ember/test-helpers DOM utilities to work without Ember / Glimmer.

@@ -0,0 +1,58 @@
import { consume, tagFor, dirtyTagFor } from '@glimmer/validator';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just author this in .ts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is impossible, you can't have new TrackedObject return anything but a TrackedObject if you author it as a TS class, and there's no way to tell TS that this TrackedObject should get the same keys as the object passed to it. @chriskrycho and I noodled on this for a while with tracked-built-ins, and this was the only way I found you could get the expected behavior.

That aside, Proxy itself is very difficult to type correctly. I haven't been able to figure out a way to type the handlers of a Proxy without casting to any multiple times yet. So, I'm not sure TS would help us much with the implementation here.

Comment on lines -142 to -153
propertyDidChange();
},
};
}

// eslint-disable-next-line @typescript-eslint/no-empty-function
let propertyDidChange = function(): void {};

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function setPropertyDidChange(cb: () => void) {
propertyDidChange = cb;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you help me understand this change? Do we not need to be able to customize this anymore?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a mistake I made earlier, propertyDidChange already exists in the getter/setter setup from @glimmer/validator. This meant there were two different propertyDidChange callbacks being fired.

@pzuraq
Copy link
Member Author

pzuraq commented Mar 27, 2020

I made an issue to track some of the ongoing problems/pain points with the current testing harness: #246

@pzuraq pzuraq merged commit a081811 into master Mar 27, 2020
@pzuraq pzuraq deleted the feat/modifier-managers branch March 27, 2020 20:13
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants