Skip to content

Commit 1e32a2a

Browse files
committed
Fixes the issue by punting on generators completely
1 parent 163c173 commit 1e32a2a

File tree

10 files changed

+114
-85
lines changed

10 files changed

+114
-85
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@
6969
"it",
7070
"expect",
7171
"td",
72-
"assert"
72+
"assert",
73+
"ES_SUPPORT"
7374
],
7475
"ignore": [
7576
"dist",

src/imitate/overwrite-children/gather-props.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import _ from '../../wrap/lodash'
22

3-
import isPrimitiveLike from './is-primitive-like'
3+
import isFakeable from './is-fakeable'
44

55
export default (thing) => {
66
const originalThing = thing
77
const props = {}
88

9-
while (!isPrimitiveLike(thing) && !isNativePrototype(thing)) {
9+
while (isFakeable(thing) && !isNativePrototype(thing)) {
1010
Object.getOwnPropertyNames(thing).forEach((propName) => {
1111
if (!props[propName] && propName !== 'constructor') {
1212
props[propName] = Object.getOwnPropertyDescriptor(thing, propName)

src/imitate/overwrite-children/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import _ from '../../wrap/lodash'
22

3-
import isPrimitiveLike from './is-primitive-like'
3+
import isFakeable from './is-fakeable'
44
import gatherProps from './gather-props'
55
import copyProps from './copy-props'
66
import chainPrototype from './chain-prototype'
77

88
export default (original, target, overwriteChild) => {
9-
if (isPrimitiveLike(target)) return
9+
if (!isFakeable(target)) return
1010

1111
if (_.isArray(target)) {
1212
_.each(original, (item, index) =>

src/imitate/overwrite-children/is-primitive-like.js renamed to src/imitate/overwrite-children/is-fakeable.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import _ from '../../wrap/lodash'
2+
import isGenerator from '../is-generator'
23

34
export default (thing) =>
4-
!_.isObject(thing) || _.compact([
5+
!(!_.isObject(thing) || isBoxedType(thing) || isGenerator(thing))
6+
7+
const isBoxedType = (thing) =>
8+
_.compact([
59
Boolean,
610
Date,
711
Number,

test/helper.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ module.exports = {
1919
afterAll: function () {}
2020
}
2121

22-
global.ES_GENERATOR_SUPPORT = (function () {
23-
try {
24-
eval('(function* () {})')
25-
return true
26-
} catch (e) {
27-
return false
28-
}
29-
})()
22+
global.ES_SUPPORT = {
23+
GENERATORS: (function () {
24+
try {
25+
eval('(function* () {})') // eslint-disable-line
26+
return true
27+
} catch (e) {
28+
return false
29+
}
30+
})()
31+
}

test/safe/imitate/index.test.js

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -93,42 +93,60 @@ module.exports = {
9393
assert.equal(explain(result.shirt).name, 'pants.shirt')
9494
assert.equal(explain(result.shirt.tie).name, 'pants.shirt.tie')
9595
},
96-
'names prototypal things okay': () => {
97-
class Thing {
98-
doStuff () {}
99-
}
100-
Thing.prototype.doStuff.bar = { baz: function () {} }
101-
102-
const result = subject(Thing)
103-
104-
assert.equal(explain(result).name, 'Thing')
105-
assert.equal(explain(result.prototype.doStuff).name, 'Thing.prototype.doStuff')
106-
assert.equal(explain(result.prototype.doStuff.bar.baz).name, 'Thing.prototype.doStuff.bar.baz')
107-
},
108-
'name array things okay': () => {
96+
'skips over generator functions, even their custom properties': () => {
97+
// This is currently unsupported, expect to kill this test someday
98+
if (!ES_SUPPORT.GENERATORS) return
10999
const original = {
110-
items: [
111-
function () {},
112-
function withName () {},
113-
() => false,
114-
{
115-
biz: function () {}
116-
}
117-
]
100+
func: eval('(function* () {})') // eslint-disable-line
118101
}
102+
const otherRef = {}
103+
original.func.customProp = otherRef
119104

120105
const result = subject(original)
121106

122-
assert.equal(explain(result.items[0]).name, '.items[0]')
123-
assert.equal(explain(result.items[1]).name, '.items[1]')
124-
assert.equal(explain(result.items[2]).name, '.items[2]')
125-
assert.equal(explain(result.items[3].biz).name, '.items[3].biz')
107+
assert.strictEqual(result.func, original.func)
108+
assert.strictEqual(result.func.customProp, otherRef) // e.g. NOT cloned
126109
},
127-
'other top level things are named fine': () => {
128-
assert.equal(explain(subject([() => 1])[0]).name, '[0]')
129-
const foo = (function () { return function () {} })()
130-
foo.bar = function () {}
131-
assert.equal(explain(subject(foo)).name, '(anonymous function)')
132-
assert.equal(explain(subject(foo).bar).name, '.bar')
110+
'naming stuff': {
111+
'prototypal things': () => {
112+
class Thing {
113+
doStuff () {}
114+
}
115+
Thing.prototype.doStuff.bar = { baz: function () {} }
116+
117+
const result = subject(Thing)
118+
119+
assert.equal(explain(result).name, 'Thing')
120+
assert.equal(explain(result.prototype.doStuff).name,
121+
'Thing.prototype.doStuff')
122+
assert.equal(explain(result.prototype.doStuff.bar.baz).name,
123+
'Thing.prototype.doStuff.bar.baz')
124+
},
125+
'array things': () => {
126+
const original = {
127+
items: [
128+
function () {},
129+
function withName () {},
130+
() => false,
131+
{
132+
biz: function () {}
133+
}
134+
]
135+
}
136+
137+
const result = subject(original)
138+
139+
assert.equal(explain(result.items[0]).name, '.items[0]')
140+
assert.equal(explain(result.items[1]).name, '.items[1]')
141+
assert.equal(explain(result.items[2]).name, '.items[2]')
142+
assert.equal(explain(result.items[3].biz).name, '.items[3].biz')
143+
},
144+
'other top level things': () => {
145+
assert.equal(explain(subject([() => 1])[0]).name, '[0]')
146+
const foo = (function () { return function () {} })()
147+
foo.bar = function () {}
148+
assert.equal(explain(subject(foo)).name, '(anonymous function)')
149+
assert.equal(explain(subject(foo).bar).name, '.bar')
150+
}
133151
}
134152
}

test/unit/imitate/is-generator.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ module.exports = {
99
assert.strictEqual(result, false)
1010
},
1111
'returns true if passed a generator (when generators supported)': () => {
12-
if (!ES_GENERATOR_SUPPORT) return
13-
const func = eval('(function* () {})') //esline-disable-line
12+
if (!ES_SUPPORT.GENERATORS) return
13+
const func = eval('(function* () {})') // eslint-disable-line
1414

1515
const result = subject(func)
1616

1717
assert.strictEqual(result, true)
1818
},
1919
'returns false when generators are not supported': () => {
20-
if (ES_GENERATOR_SUPPORT) return
20+
if (ES_SUPPORT.GENERATORS) return
2121
// Not much of a test, ¯\_(ツ)_/¯
2222
assert.strictEqual(subject(), false)
2323
}

test/unit/imitate/overwrite-children/index.test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
let gatherProps, copyProps, isPrimitiveLike, chainPrototype, subject
1+
let gatherProps, copyProps, isFakeable, chainPrototype, subject
22
module.exports = {
33
beforeEach: () => {
44
gatherProps = td.replace('../../../../src/imitate/overwrite-children/gather-props').default
55
copyProps = td.replace('../../../../src/imitate/overwrite-children/copy-props').default
6-
isPrimitiveLike = td.replace('../../../../src/imitate/overwrite-children/is-primitive-like').default
6+
isFakeable = td.replace('../../../../src/imitate/overwrite-children/is-fakeable').default
77
chainPrototype = td.replace('../../../../src/imitate/overwrite-children/chain-prototype').default
88
subject = require('../../../../src/imitate/overwrite-children').default
99

10-
td.when(isPrimitiveLike(td.matchers.anything())).thenReturn(false)
10+
td.when(isFakeable(td.matchers.anything())).thenReturn(true)
1111
},
12-
'target is primitive-like (then do nothing)': () => {
13-
td.when(isPrimitiveLike('some target')).thenReturn(true)
12+
'target is not fakeable (then do nothing)': () => {
13+
td.when(isFakeable('some target')).thenReturn(false)
1414

1515
subject('some original', 'some target', () => { throw new Error('do not fire!') })
1616

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import subject from '../../../../src/imitate/overwrite-children/is-fakeable'
2+
3+
module.exports = {
4+
'identifies primitive things': () => {
5+
assert.equal(subject(), false)
6+
assert.equal(subject(true), false)
7+
assert.equal(subject(false), false)
8+
assert.equal(subject(undefined), false)
9+
assert.equal(subject(null), false)
10+
assert.equal(subject(1), false)
11+
assert.equal(subject('hi'), false)
12+
assert.equal(subject(NaN), false)
13+
},
14+
'identifies symbols': () => {
15+
if (!global.Symbol) return
16+
17+
assert.equal(subject(Symbol.species), false)
18+
},
19+
'identifies boxed types and basic value types': () => {
20+
assert.equal(subject(new String('hi')), false) // eslint-disable-line
21+
assert.equal(subject(new Boolean(false)), false) // eslint-disable-line
22+
assert.equal(subject(new Number(0)), false) // eslint-disable-line
23+
assert.equal(subject(/hi/), false)
24+
assert.equal(subject(new Date()), false)
25+
},
26+
'gives functions, arrays, and custom objects a pass': () => {
27+
assert.equal(subject(new Object()), true) // eslint-disable-line
28+
assert.equal(subject(function () {}), true)
29+
assert.equal(subject([]), true)
30+
assert.equal(subject({}), true)
31+
},
32+
'generators are not fakeable': () => {
33+
if (!ES_SUPPORT.GENERATORS) return
34+
assert.equal(subject(eval('(function* (){})')), false) // eslint-disable-line
35+
}
36+
}

test/unit/imitate/overwrite-children/is-primitive-like.test.js

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)