Skip to content

Commit

Permalink
Allows fragment updates to happen after state updates
Browse files Browse the repository at this point in the history
Proposed fix for #1520. Provides a starting point for discussion.
  • Loading branch information
jacwright committed Aug 15, 2018
1 parent 9eec6f8 commit 4bc743e
Show file tree
Hide file tree
Showing 60 changed files with 1,115 additions and 174 deletions.
2 changes: 1 addition & 1 deletion src/compile/dom/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export default function dom(
? `@proto`
: deindent`
{
${['destroy', 'get', 'fire', 'on', 'set', '_set', '_mount', '_differs']
${['destroy', 'get', 'fire', 'on', 'set', '_set', '_updateFragment', '_mount', '_differs']
.map(n => `${n}: @${n}`)
.join(',\n')}
}`;
Expand Down
24 changes: 21 additions & 3 deletions src/shared/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,20 +96,36 @@ export function set(newState) {
this.root._lock = false;
}

export function _set(newState) {
export function _set(newState, options) {
var oldState = this._state,
changed = {},
changed = this._changed || {},
dirty = false;

for (var key in newState) {
if (this._differs(newState[key], oldState[key])) changed[key] = dirty = true;
}
if (!dirty) return;
if (!dirty) return false;

this._state = assign(assign({}, oldState), newState);
this._recompute(changed, this._state);
if (this._bind) this._bind(changed, this._state);

if (!this._changed) {
this._changed = changed;
this._oldState = oldState;
}

if (!options || !options.skipUpdate) this._updateFragment();

return true;
}

export function _updateFragment() {
if (!this._changed) return;
var changed = this._changed,
oldState = this._oldState;
this._changed = this._oldState = null;

if (this._fragment) {
this.fire("state", { changed: changed, current: this._state, previous: oldState });
this._fragment.p(changed, this._state);
Expand Down Expand Up @@ -152,6 +168,7 @@ export var proto = {
set,
_recompute: noop,
_set,
_updateFragment,
_mount,
_differs
};
Expand All @@ -164,6 +181,7 @@ export var protoDev = {
set: setDev,
_recompute: noop,
_set,
_updateFragment,
_mount,
_differs
};
13 changes: 9 additions & 4 deletions store.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ assign(Store.prototype, {
});

const dependents = this._dependents.slice(); // guard against mutations
for (let i = 0; i < dependents.length; i += 1) {
const dependent = dependents[i];
const options = { skipUpdate: true };
const dirtyDependents = dependents.filter(dependent => {
const componentState = {};
let dirty = false;

Expand All @@ -74,8 +74,13 @@ assign(Store.prototype, {
}
}

if (dirty) dependent.component.set(componentState);
}
if (dirty) {
dependent.component._set(componentState, options);
return true;
}
});

dirtyDependents.forEach(dependent => dependent.component._updateFragment());

this.fire('update', {
changed,
Expand Down
23 changes: 20 additions & 3 deletions test/cli/samples/basic/expected/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ assign(Main.prototype, {
on: on,
set: set,
_set: _set,
_updateFragment: _updateFragment,
_mount: _mount,
_differs: _differs
});
Expand Down Expand Up @@ -132,20 +133,36 @@ function set(newState) {
this.root._lock = false;
}

function _set(newState) {
function _set(newState, options) {
var oldState = this._state,
changed = {},
changed = this._changed || {},
dirty = false;

for (var key in newState) {
if (this._differs(newState[key], oldState[key])) changed[key] = dirty = true;
}
if (!dirty) return;
if (!dirty) return false;

this._state = assign(assign({}, oldState), newState);
this._recompute(changed, this._state);
if (this._bind) this._bind(changed, this._state);

if (!this._changed) {
this._changed = changed;
this._oldState = oldState;
}

if (!options || !options.skipUpdate) this._updateFragment();

return true;
}

function _updateFragment() {
if (!this._changed) return;
var changed = this._changed,
oldState = this._oldState;
this._changed = this._oldState = null;

if (this._fragment) {
this.fire("state", { changed: changed, current: this._state, previous: oldState });
this._fragment.p(changed, this._state);
Expand Down
23 changes: 20 additions & 3 deletions test/cli/samples/custom-element/expected/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ assign(Main.prototype, {
on: on,
set: set,
_set: _set,
_updateFragment: _updateFragment,
_mount: _mount,
_differs: _differs
});
Expand Down Expand Up @@ -153,20 +154,36 @@ function set(newState) {
this.root._lock = false;
}

function _set(newState) {
function _set(newState, options) {
var oldState = this._state,
changed = {},
changed = this._changed || {},
dirty = false;

for (var key in newState) {
if (this._differs(newState[key], oldState[key])) changed[key] = dirty = true;
}
if (!dirty) return;
if (!dirty) return false;

this._state = assign(assign({}, oldState), newState);
this._recompute(changed, this._state);
if (this._bind) this._bind(changed, this._state);

if (!this._changed) {
this._changed = changed;
this._oldState = oldState;
}

if (!options || !options.skipUpdate) this._updateFragment();

return true;
}

function _updateFragment() {
if (!this._changed) return;
var changed = this._changed,
oldState = this._oldState;
this._changed = this._oldState = null;

if (this._fragment) {
this.fire("state", { changed: changed, current: this._state, previous: oldState });
this._fragment.p(changed, this._state);
Expand Down
23 changes: 20 additions & 3 deletions test/cli/samples/dev/expected/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ assign(Main.prototype, {
on: on,
set: setDev,
_set: _set,
_updateFragment: _updateFragment,
_mount: _mount,
_differs: _differs
});
Expand Down Expand Up @@ -154,20 +155,36 @@ function setDev(newState) {
set.call(this, newState);
}

function _set(newState) {
function _set(newState, options) {
var oldState = this._state,
changed = {},
changed = this._changed || {},
dirty = false;

for (var key in newState) {
if (this._differs(newState[key], oldState[key])) changed[key] = dirty = true;
}
if (!dirty) return;
if (!dirty) return false;

this._state = assign(assign({}, oldState), newState);
this._recompute(changed, this._state);
if (this._bind) this._bind(changed, this._state);

if (!this._changed) {
this._changed = changed;
this._oldState = oldState;
}

if (!options || !options.skipUpdate) this._updateFragment();

return true;
}

function _updateFragment() {
if (!this._changed) return;
var changed = this._changed,
oldState = this._oldState;
this._changed = this._oldState = null;

if (this._fragment) {
this.fire("state", { changed: changed, current: this._state, previous: oldState });
this._fragment.p(changed, this._state);
Expand Down
23 changes: 20 additions & 3 deletions test/cli/samples/dir-sourcemap/expected/Main.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion test/cli/samples/dir-sourcemap/expected/Main.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 20 additions & 3 deletions test/cli/samples/dir-sourcemap/expected/Widget.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion test/cli/samples/dir-sourcemap/expected/Widget.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 20 additions & 3 deletions test/cli/samples/dir-subdir/expected/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ assign(Main.prototype, {
on: on,
set: set,
_set: _set,
_updateFragment: _updateFragment,
_mount: _mount,
_differs: _differs
});
Expand Down Expand Up @@ -140,20 +141,36 @@ function set(newState) {
this.root._lock = false;
}

function _set(newState) {
function _set(newState, options) {
var oldState = this._state,
changed = {},
changed = this._changed || {},
dirty = false;

for (var key in newState) {
if (this._differs(newState[key], oldState[key])) changed[key] = dirty = true;
}
if (!dirty) return;
if (!dirty) return false;

this._state = assign(assign({}, oldState), newState);
this._recompute(changed, this._state);
if (this._bind) this._bind(changed, this._state);

if (!this._changed) {
this._changed = changed;
this._oldState = oldState;
}

if (!options || !options.skipUpdate) this._updateFragment();

return true;
}

function _updateFragment() {
if (!this._changed) return;
var changed = this._changed,
oldState = this._oldState;
this._changed = this._oldState = null;

if (this._fragment) {
this.fire("state", { changed: changed, current: this._state, previous: oldState });
this._fragment.p(changed, this._state);
Expand Down
Loading

0 comments on commit 4bc743e

Please sign in to comment.