-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #75 from mydea/fn/use-preprocessor
Ensure polyfill works properly with Ember 3.27+
- Loading branch information
Showing
10 changed files
with
1,234 additions
and
267 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { createCache, getValue } from '@glimmer/tracking/primitives/cache'; | ||
import { assert } from '@ember/debug'; | ||
|
||
export function cached(...args) { | ||
const [target, key, descriptor] = args; | ||
|
||
// Error on `@cached()`, `@cached(...args)`, and `@cached propName = value;` | ||
assert( | ||
'You attempted to use @cached(), which is not necessary nor supported. Remove the parentheses and you will be good to go!', | ||
target !== undefined | ||
); | ||
assert( | ||
`You attempted to use @cached on with ${ | ||
args.length > 1 ? 'arguments' : 'an argument' | ||
} ( @cached(${args | ||
.map(d => `'${d}'`) | ||
.join( | ||
', ' | ||
)}), which is not supported. Dependencies are automatically tracked, so you can just use ${'`@cached`'}`, | ||
typeof target === 'object' && | ||
typeof key === 'string' && | ||
typeof descriptor === 'object' && | ||
args.length === 3 | ||
); | ||
assert( | ||
`The @cached decorator must be applied to getters. '${key}' is not a getter.`, | ||
typeof descriptor.get == 'function' | ||
); | ||
|
||
const caches = new WeakMap(); | ||
const getter = descriptor.get; | ||
descriptor.get = function () { | ||
if (!caches.has(this)) caches.set(this, createCache(getter.bind(this))); | ||
return getValue(caches.get(this)); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,22 @@ | ||
'use strict'; | ||
|
||
const { resolve } = require('path'); | ||
const { hasPlugin, addPlugin } = require('ember-cli-babel-plugin-helpers'); | ||
|
||
module.exports = { | ||
name: require('./package').name, | ||
|
||
included() { | ||
this._super.included.apply(this, arguments); | ||
this._ensureThisImport(); | ||
|
||
this.import('vendor/ember-cached-decorator-polyfill/index.js'); | ||
this.patchEmberModulesAPIPolyfill(); | ||
this.addBabelPlugin(); | ||
}, | ||
|
||
treeForVendor(tree) { | ||
const babel = this.addons.find(a => a.name === 'ember-cli-babel'); | ||
addBabelPlugin() { | ||
let app = this._findHost(); | ||
|
||
return babel.transpileTree(tree, { | ||
babel: this.options.babel, | ||
|
||
'ember-cli-babel': { | ||
compileModules: false | ||
} | ||
}); | ||
}, | ||
|
||
_ensureThisImport() { | ||
if (!this.import) { | ||
this._findHost = function findHostShim() { | ||
let current = this; | ||
let app; | ||
do { | ||
app = current.app || app; | ||
// eslint-disable-next-line no-cond-assign | ||
} while (current.parent.parent && (current = current.parent)); | ||
return app; | ||
}; | ||
this.import = function importShim(asset, options) { | ||
const app = this._findHost(); | ||
app.import(asset, options); | ||
}; | ||
if (!hasPlugin(app, 'ember-cache-decorator-polyfill')) { | ||
addPlugin(app, resolve(__dirname, './lib/transpile-modules.js')); | ||
} | ||
}, | ||
|
||
patchEmberModulesAPIPolyfill() { | ||
const babel = this.parent.findOwnAddonByName | ||
? this.parent.findOwnAddonByName('ember-cli-babel') // parent is an addon | ||
: this.parent.findAddonByName('ember-cli-babel'); // parent is an app | ||
|
||
if (babel.__CachedDecoratorPolyfillApplied) return; | ||
babel.__CachedDecoratorPolyfillApplied = true; | ||
|
||
const { _getEmberModulesAPIPolyfill } = babel; | ||
babel._getEmberModulesAPIPolyfill = function (...args) { | ||
const plugins = _getEmberModulesAPIPolyfill.apply(this, args); | ||
if (!plugins) return; | ||
|
||
return [[resolve(__dirname, './lib/transpile-modules.js')], ...plugins]; | ||
}; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { module, test } from 'qunit'; | ||
import { cached, tracked } from '@glimmer/tracking'; | ||
|
||
module('Unit | Import | followed import', function () { | ||
test('it works', function (assert) { | ||
class Person { | ||
@tracked firstName = 'Jen'; | ||
lastName = 'Weber'; | ||
|
||
@cached | ||
get fullName() { | ||
const fullName = `${this.firstName} ${this.lastName}`; | ||
assert.step(fullName); | ||
return fullName; | ||
} | ||
} | ||
|
||
const person = new Person(); | ||
assert.verifySteps([], 'getter is not called after class initialization'); | ||
|
||
assert.strictEqual(person.fullName, 'Jen Weber'); | ||
assert.verifySteps( | ||
['Jen Weber'], | ||
'getter was called after property access' | ||
); | ||
|
||
assert.strictEqual(person.fullName, 'Jen Weber'); | ||
assert.verifySteps( | ||
[], | ||
'getter was not called again after repeated property access' | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { module, test } from 'qunit'; | ||
// prettier-ignore | ||
import { | ||
cached, | ||
tracked | ||
} from "@glimmer/tracking"; | ||
|
||
module('Unit | Import | multi-line import', function () { | ||
test('it works', function (assert) { | ||
class Person { | ||
@tracked firstName = 'Jen'; | ||
lastName = 'Weber'; | ||
|
||
@cached | ||
get fullName() { | ||
const fullName = `${this.firstName} ${this.lastName}`; | ||
assert.step(fullName); | ||
return fullName; | ||
} | ||
} | ||
|
||
const person = new Person(); | ||
assert.verifySteps([], 'getter is not called after class initialization'); | ||
|
||
assert.strictEqual(person.fullName, 'Jen Weber'); | ||
assert.verifySteps( | ||
['Jen Weber'], | ||
'getter was called after property access' | ||
); | ||
|
||
assert.strictEqual(person.fullName, 'Jen Weber'); | ||
assert.verifySteps( | ||
[], | ||
'getter was not called again after repeated property access' | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { module, test } from 'qunit'; | ||
import { tracked, cached as localCached } from '@glimmer/tracking'; | ||
|
||
module('Unit | Import | renamed import', function () { | ||
test('it works', function (assert) { | ||
class Person { | ||
@tracked firstName = 'Jen'; | ||
lastName = 'Weber'; | ||
|
||
@localCached | ||
get fullName() { | ||
const fullName = `${this.firstName} ${this.lastName}`; | ||
assert.step(fullName); | ||
return fullName; | ||
} | ||
} | ||
|
||
const person = new Person(); | ||
assert.verifySteps([], 'getter is not called after class initialization'); | ||
|
||
assert.strictEqual(person.fullName, 'Jen Weber'); | ||
assert.verifySteps( | ||
['Jen Weber'], | ||
'getter was called after property access' | ||
); | ||
|
||
assert.strictEqual(person.fullName, 'Jen Weber'); | ||
assert.verifySteps( | ||
[], | ||
'getter was not called again after repeated property access' | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { module, test } from 'qunit'; | ||
import { cached } from '@glimmer/tracking'; | ||
|
||
module('Unit | Import | single import', function () { | ||
test('it works', function (assert) { | ||
class Person { | ||
firstName = 'Jen'; | ||
lastName = 'Weber'; | ||
|
||
@cached | ||
get fullName() { | ||
const fullName = `${this.firstName} ${this.lastName}`; | ||
assert.step(fullName); | ||
return fullName; | ||
} | ||
} | ||
|
||
const person = new Person(); | ||
assert.verifySteps([], 'getter is not called after class initialization'); | ||
|
||
assert.strictEqual(person.fullName, 'Jen Weber'); | ||
assert.verifySteps( | ||
['Jen Weber'], | ||
'getter was called after property access' | ||
); | ||
|
||
assert.strictEqual(person.fullName, 'Jen Weber'); | ||
assert.verifySteps( | ||
[], | ||
'getter was not called again after repeated property access' | ||
); | ||
}); | ||
}); |
Oops, something went wrong.