Skip to content

Commit

Permalink
Merge pull request #17 from lifeart/ref-callback-update
Browse files Browse the repository at this point in the history
[breaking] fix callback behaviour
  • Loading branch information
lifeart authored Jul 24, 2021
2 parents 24b685c + 3a9efa4 commit 6db76f8
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 10 deletions.
26 changes: 20 additions & 6 deletions addon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export {
registerNodeDestructor,
unregisterNodeDestructor,
} from "./utils/ref";

import { addPrototypeReference } from "./utils/prototype-reference";

export function nodeFor(context, name) {
return bucketFor(context).get(name);
Expand All @@ -14,7 +14,7 @@ function maybeReturnCreated(value, createdValues, fn, ctx) {
if (value === null || value === undefined) {
return null;
}
if (fn) {
if (typeof fn === 'function') {
if (!createdValues.has(value)) {
createdValues.set(value, fn.call(ctx, value));
}
Expand All @@ -24,9 +24,14 @@ function maybeReturnCreated(value, createdValues, fn, ctx) {
}
}



export function ref(name, fn) {
return function () {
return function (klass, objectKey) {
const createdValues = new WeakMap();
if (typeof fn === 'function') {
addPrototypeReference(klass, objectKey, name);
}
return {
get() {
const value = bucketFor(this).get(name);
Expand All @@ -37,8 +42,11 @@ export function ref(name, fn) {
}

export function globalRef(name, fn) {
return function () {
return function (klass, objectKey) {
const createdValues = new WeakMap();
if (typeof fn === 'function') {
addPrototypeReference(klass, objectKey, name);
}
return {
get() {
const value = bucketFor(getOwner(this) || resolveGlobalRef()).get(name);
Expand All @@ -49,8 +57,11 @@ export function globalRef(name, fn) {
}

export function trackedRef(name, fn) {
return function () {
return function (klass, objectKey) {
const createdValues = new WeakMap();
if (typeof fn === 'function') {
addPrototypeReference(klass, objectKey, name);
}
return {
get() {
const value = bucketFor(this).getTracked(name);
Expand All @@ -61,8 +72,11 @@ export function trackedRef(name, fn) {
}

export function trackedGlobalRef(name, fn) {
return function () {
return function (klass, objectKey) {
const createdValues = new WeakMap();
if (typeof fn === 'function') {
addPrototypeReference(klass, objectKey, name);
}
return {
get() {
const value = bucketFor(getOwner(this) || resolveGlobalRef()).getTracked(name);
Expand Down
11 changes: 9 additions & 2 deletions addon/modifiers/create-ref.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { getOwner } from "@ember/application";

import { action } from "@ember/object";
import { assert } from "@ember/debug";
import { setGlobalRef, bucketFor, getNodeDestructors } from "./../utils/ref";

import { setGlobalRef, bucketFor, getNodeDestructors, watchFor } from "./../utils/ref";
import { getReferencedKeys } from "../utils/prototype-reference";
export default class RefModifier extends Modifier {
_key = this.name;
_ctx = this.ctx;
Expand Down Expand Up @@ -98,6 +98,13 @@ export default class RefModifier extends Modifier {
}
this._ctx = this.ctx;
this._key = this.name;
watchFor(this.name, this.ctx, () => {
const keys = getReferencedKeys(this.ctx, this.name);
keys.forEach((keyName) => {
// consume keys with callbacks
this.ctx[keyName];
})
});
bucketFor(this.ctx).add(this.name, this.element);
if (this.isTracked) {
this.installMutationObservers();
Expand Down
27 changes: 27 additions & 0 deletions addon/utils/prototype-reference.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const PrototypeReferences = new WeakMap();

export function addPrototypeReference(klass, objectKey, referenceName) {
if (!PrototypeReferences.has(klass)) {
PrototypeReferences.set(klass, {});
}
let obj = PrototypeReferences.get(klass);
if (!(referenceName in obj)) {
obj[referenceName] = new Set();
}
obj[referenceName].add(objectKey);
}

export function getReferencedKeys(klassInstance, referenceName) {
let proto = klassInstance;
while (proto.__proto__) {
proto = proto.__proto__;
if (PrototypeReferences.has(proto)) {
let maybeData = PrototypeReferences.get(proto);
if (referenceName in maybeData) {
return Array.from(maybeData[referenceName]);
}
}
}

return [];
}
7 changes: 6 additions & 1 deletion tests/dummy/app/controllers/application.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Controller from '@ember/controller';
import { trackedRef, registerNodeDestructor } from 'ember-ref-bucket';
import { trackedRef, registerNodeDestructor, ref } from 'ember-ref-bucket';

class NodeWrapper {
constructor(node) {
Expand All @@ -22,4 +22,9 @@ export default class ApplicationController extends Controller {
get value() {
return this.node?.value();
}
@ref('bar', function(node) {
const instance = new NodeWrapper(node);
registerNodeDestructor(node, () => instance.destroy());
return instance;
}) barNode;
}
2 changes: 1 addition & 1 deletion tests/dummy/app/templates/application.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h2 id="title" contenteditable {{create-tracked-ref "foo" subtree=true}}><span>Welcome to Ember</span></h2>

{{#let (tracked-ref-to "foo") as |node|}}
<br />
<br {{create-ref "bar"}}/>
Content: {{node.textContent}}
<br />
Child nodes: {{node.children.length}}
Expand Down

0 comments on commit 6db76f8

Please sign in to comment.