Skip to content

Commit

Permalink
fix(cache): Clear deps and context when get value from cache (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
smalluban authored Jan 8, 2024
1 parent ffba323 commit ec6f8b1
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 10 deletions.
33 changes: 23 additions & 10 deletions src/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,10 @@ function dispatch(entry) {
while (entry) {
entry.resolved = false;

if (entry.deps) {
for (const depEntry of entry.deps) {
depEntry.contexts.delete(entry);
}
entry.deps.clear();
}

if (entry.contexts) {
for (const context of entry.contexts) {
if (!stack.has(context)) {
if (!contexts.includes(context)) contexts.push(context);
entry.contexts.delete(context);
if (!stack.has(context) && !contexts.includes(context)) {
contexts.push(context);
}
}
}
Expand Down Expand Up @@ -79,6 +71,13 @@ export function get(target, key, getter) {

if (entry.resolved) return entry.value;

if (entry.deps) {
for (const depEntry of entry.deps) {
depEntry.contexts.delete(entry);
}
entry.deps.clear();
}

const lastContext = context;

try {
Expand Down Expand Up @@ -173,6 +172,20 @@ function invalidateEntry(entry, options) {
}

if (options.deleteEntry) {
if (entry.deps) {
for (const depEntry of entry.deps) {
depEntry.contexts.delete(entry);
}
entry.deps = undefined;
}

if (entry.contexts) {
for (const context of entry.contexts) {
context.deps.delete(entry);
}
entry.contexts = undefined;
}

deleteEntry(entry);
}
}
Expand Down
51 changes: 51 additions & 0 deletions test/spec/define.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,57 @@ describe("define:", () => {
});
});

// Relates to https://github.com/hybridsjs/hybrids/issues/229
// with a move of clearing deps and context in cache
// There is still a problem with "prop3" which is not updated in render
// but it happens because the render was already called after the prop1 observer
it("render method is called when observed chain of properties changes", () => {
define({
tag: "test-define-render-observed",
prop1: {
value: 0,
observe(host, value) {
host.prop2 = value;
},
},
prop2: {
value: 0,
observe(host, value) {
host.prop3 = value;
},
},
prop3: 0,
render: ({ prop1, prop2, prop3 }) =>
// prettier-ignore
html`<div>${prop1}</div><div>${prop2}</div><div>${prop3}</div>`,
});

el = document.createElement("test-define-render-observed");
document.body.appendChild(el);

return resolveRaf(() => {
expect(el.shadowRoot.innerHTML).toBe(
"<div>0</div><div>0</div><div>0</div>",
);

el.prop1 = 1;

return resolveRaf(() => {
expect(el.shadowRoot.innerHTML).toBe(
"<div>1</div><div>1</div><div>0</div>",
);

el.prop1 = 2;

return resolveRaf(() => {
expect(el.shadowRoot.innerHTML).toBe(
"<div>2</div><div>2</div><div>1</div>",
);
});
});
});
});

describe("created element", () => {
beforeAll(() => {
define({
Expand Down

0 comments on commit ec6f8b1

Please sign in to comment.