Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove circular ref and golf implementation #2517

Merged
merged 10 commits into from
Nov 11, 2020
Merged
9 changes: 8 additions & 1 deletion compat/test/browser/cloneElement.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,17 @@ describe('compat cloneElement', () => {
a<span>b</span>
</foo>
);
expect(cloneElement(element)).to.eql(element);
const clone = cloneElement(element);
delete clone._original;
delete element._original;
expect(clone).to.eql(element);
});

it('should support props.children', () => {
let element = <foo children={<span>b</span>} />;
let clone = cloneElement(element);
delete clone._original;
delete element._original;
expect(clone).to.eql(element);
expect(cloneElement(clone).props.children).to.eql(element.props.children);
});
Expand All @@ -37,6 +42,8 @@ describe('compat cloneElement', () => {
</foo>
);
let clone = cloneElement(element);
delete clone._original;
delete element._original;
expect(clone).to.eql(element);
expect(clone.props.children.type).to.eql('div');
});
Expand Down
3 changes: 1 addition & 2 deletions jsx-runtime/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ function createVNode(type, props, key, __source, __self) {
_component: null,
_hydrating: null,
constructor: undefined,
_original: undefined,
_original: ++options._vnodeId,
__source,
__self
};
vnode._original = vnode;

// If a Component VNode, check for and apply defaultProps.
// Note: `type` is often a String, and can be `undefined` in development.
Expand Down
2 changes: 2 additions & 0 deletions jsx-runtime/test/browser/jsx-runtime.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ describe('Babel jsx/jsxDEV', () => {
const jsxVNode = jsx('div', { class: 'foo' }, 'key');
delete jsxVNode.__self;
delete jsxVNode.__source;
delete jsxVNode._original;
delete elementVNode._original;
expect(jsxVNode).to.deep.equal(elementVNode);
});
});
1 change: 1 addition & 0 deletions mangle.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"props": {
"cname": 6,
"props": {
"$_vnodeId": "__v",
"$_cleanup": "__c",
"$_afterPaintQueued": "__a",
"$__hooks": "__H",
Expand Down
2 changes: 1 addition & 1 deletion src/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ function renderComponent(component) {
if (parentDom) {
let commitQueue = [];
const oldVNode = assign({}, vnode);
oldVNode._original = oldVNode;
oldVNode._original = vnode._original + 1;

let newDom = diff(
parentDom,
Expand Down
3 changes: 1 addition & 2 deletions src/create-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,9 @@ export function createVNode(type, props, key, ref, original) {
_component: null,
_hydrating: null,
constructor: undefined,
_original: original
_original: original == null ? ++options._vnodeId : original
};

if (original == null) vnode._original = vnode;
if (options.vnode != null) options.vnode(vnode);

return vnode;
Expand Down
1 change: 1 addition & 0 deletions src/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface DevSource {
}

export interface Options extends preact.Options {
_vnodeId: number;
/** Attach a hook that is invoked before render, mainly to check the arguments. */
_root?(
vnode: preact.ComponentChild,
Expand Down
3 changes: 2 additions & 1 deletion src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { _catchError } from './diff/catch-error';
* @type {import('./internal').Options}
*/
const options = {
_catchError
_catchError,
_vnodeId: 0
};

export default options;
56 changes: 39 additions & 17 deletions test/shared/createElement.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,11 @@ describe('createElement(jsx)', () => {
});

it('should support nested children', () => {
const m = x => h(x);
const m = x => {
const result = h(x);
delete result._original;
return result;
};
expect(h('foo', null, m('a'), [m('b'), m('c')], m('d')))
.to.have.nested.property('props.children')
.that.eql([m('a'), [m('b'), m('c')], m('d')]);
Expand Down Expand Up @@ -158,34 +162,47 @@ describe('createElement(jsx)', () => {
});

it('should NOT set children prop when null', () => {
let r = h('foo', {foo : 'bar'}, null);
let r = h('foo', { foo: 'bar' }, null);

expect(r)
.to.be.an('object')
.to.have.nested.property('props.foo')
.not.to.have.nested.property('props.children')

})
.not.to.have.nested.property('props.children');
});

it('should NOT set children prop when unspecified', () => {
let r = h('foo', {foo : 'bar'});
let r = h('foo', { foo: 'bar' });

expect(r)
.to.be.an('object')
.to.have.nested.property('props.foo')
.not.to.have.nested.property('props.children')
})
.not.to.have.nested.property('props.children');
});

it('should NOT merge adjacent text children', () => {
const bar = h('bar');
const barClone = h('bar');
const baz = h('baz');
const bazClone = h('baz');
const baz2 = h('baz');
const baz2Clone = h('baz');

delete bar._original;
delete barClone._original;
delete baz._original;
delete bazClone._original;
delete baz2._original;
delete baz2Clone._original;

let r = h(
'foo',
null,
'one',
'two',
h('bar'),
bar,
'three',
h('baz'),
h('baz'),
baz,
baz2,
'four',
null,
'five',
Expand All @@ -198,10 +215,10 @@ describe('createElement(jsx)', () => {
.that.deep.equals([
'one',
'two',
h('bar'),
barClone,
'three',
h('baz'),
h('baz'),
bazClone,
baz2Clone,
'four',
null,
'five',
Expand Down Expand Up @@ -233,7 +250,7 @@ describe('createElement(jsx)', () => {
null
]);
});

it('should not merge children that are boolean values', () => {
let r = h('foo', null, 'one', true, 'two', false, 'three');

Expand All @@ -254,10 +271,15 @@ describe('createElement(jsx)', () => {
});

it('should ignore props.children if children are manually specified', () => {
expect(
const element = (
<div a children={['a', 'b']}>
c
</div>
).to.eql(<div a>c</div>);
);
const childrenless = <div a>c</div>;
delete element._original;
delete childrenless._original;

expect(element).to.eql(childrenless);
});
});