Skip to content

Commit

Permalink
Merge pull request #434 from machty/mf-encapsulated_task_proxy_this
Browse files Browse the repository at this point in the history
Expose TaskInstance state inside encapsulated tasks
  • Loading branch information
maxfierke authored Jul 29, 2021
2 parents a7223c0 + c2fca59 commit 879509a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
26 changes: 23 additions & 3 deletions addon/-private/task.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ if (TRACKED_INITIAL_TASK_STATE) {

Object.assign(Task.prototype, TASKABLE_MIXIN);

const currentTaskInstanceSymbol = '__ec__encap_current_ti';
export class EncapsulatedTask extends Task {
constructor(options) {
super(options);
Expand All @@ -297,15 +298,31 @@ export class EncapsulatedTask extends Task {
this._encapsulatedTaskInstanceProxies = new WeakMap();
}

_getEncapsulatedTaskClass() {
let encapsulatedTaskImplClass = this._encapsulatedTaskImplClass;

if (!encapsulatedTaskImplClass) {
encapsulatedTaskImplClass = EmberObject.extend(this.taskObj, {
unknownProperty(key) {
let currentInstance = this[currentTaskInstanceSymbol];
return currentInstance ? currentInstance[key] : undefined;
},
});
}

return encapsulatedTaskImplClass;
}

_taskInstanceFactory(args, performType) {
let owner = getOwner(this.context);
let encapsulatedTaskImpl = EmberObject.extend(this.taskObj).create({
let taskInstanceProxy;
let encapsulatedTaskImpl = this._getEncapsulatedTaskClass().create({
context: this.context,
});
setOwner(encapsulatedTaskImpl, owner);

let generatorFactory = () =>
encapsulatedTaskImpl.perform.apply(encapsulatedTaskImpl, args);
encapsulatedTaskImpl.perform.apply(taskInstanceProxy, args);
let taskInstance = new TaskInstance({
task: this,
args,
Expand All @@ -317,10 +334,13 @@ export class EncapsulatedTask extends Task {
performType,
hasEnabledEvents: this.hasEnabledEvents,
});
encapsulatedTaskImpl[currentTaskInstanceSymbol] = taskInstance;

this._encapsulatedTaskStates.set(taskInstance, encapsulatedTaskImpl);

return this._wrappedEncapsulatedTaskInstance(taskInstance);
taskInstanceProxy = this._wrappedEncapsulatedTaskInstance(taskInstance);

return taskInstanceProxy;
}

_wrappedEncapsulatedTaskInstance(taskInstance) {
Expand Down
26 changes: 26 additions & 0 deletions tests/unit/encapsulated-task-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { run } from '@ember/runloop';
import RSVP from 'rsvp';
import EmberObject from '@ember/object';
import { reads } from '@ember/object/computed';
import { task } from 'ember-concurrency';
import { module, test } from 'qunit';
import { decoratorTest } from '../helpers/helpers';
Expand Down Expand Up @@ -85,6 +86,31 @@ module('Unit: EncapsulatedTask', function () {
assert.equal(value, 'pickle');
});

test('encapsulated tasks can access task instance context', async function (assert) {
assert.expect(2);

let defer;
let Obj = EmberObject.extend({
myTask: task({
amIRunning: reads('isRunning'),

*perform() {
defer = RSVP.defer();
yield defer.promise;
return 'blah';
},
}),
});

let obj = Obj.create();
const taskInstance = obj.get('myTask').perform();
assert.equal(taskInstance.amIRunning, true);

defer.resolve();
await taskInstance;
assert.equal(taskInstance.amIRunning, false);
});

decoratorTest(
'encapsulated tasks work with native ES classes and decorators',
function (assert) {
Expand Down

0 comments on commit 879509a

Please sign in to comment.