Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Unify values returned in data.output during view-to-model conversion #933

Merged
merged 4 commits into from
Apr 25, 2017

Conversation

scofalik
Copy link
Contributor

@scofalik scofalik commented Apr 24, 2017

Suggested merge commit message (convention)

Fix: Unified values returned in data.output during view-to-model conversion. See breaking changes. Closes ckeditor/ckeditor5#4056.

BREAKING CHANGE: ViewConversionDispatcher.convert now always returns model.DocumentFragment (which may be empty in various cases). conversionApi#convertItem can pass only model.Node or model.DocumentFragment or null to data.output. Warning will be logged if different value was passed. conversionApi#convertChildren now always returns model.DocumentFragment.

@Reinmar
Copy link
Member

Reinmar commented Apr 24, 2017

Mmm... I'm unsure about this. Shouldn't we ensure that no method returns an array rather than post-convert this to DFs?

@scofalik
Copy link
Contributor Author

scofalik commented Apr 24, 2017

Well, it depends.

On one hand it feels safer.

On the other hand you imply that view conversion always is to model. We struggled to not do this, but as we can see now: it had no point (it was a nice idea) and we already lost (markers has to be handled there and this already makes ViewConversionDispatcher depend on model). Still, different methods use conversionApi.convertChildren for different purposes.

However since you can do: modelElement.appendChildren( modelFragment ) and new ModelElement( 'xxx', null, modelFragment ) I can agree that it might be better to just return model.DocumentFragment in ViewConversionDispatcher.

@scofalik
Copy link
Contributor Author

Okay, I have changed the solution, more info in the first post.

log.warn( 'view-conversion-dispatcher-item-not-converted: Item has not been converted (output is undefined).', input );

data.output = null;
} else if ( !( data.output instanceof ModelNode || data.output instanceof ModelDocumentFragment ) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to comment that it'd be better if we used duck typing with is() as it's safer. But I can see that we use a lot of instanceofs around our code still so we can change this at once in the future.

@@ -180,6 +179,30 @@ export default class ViewConversionDispatcher {
this.fire( 'documentFragment', data, consumable, this.conversionApi );
}

// Handle incorrect `data.output`.
if ( data.output === undefined ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really needed and correct? In what situations does it help?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed correct when I was working just on the dispatcher but "in real life" I can see that this is actually incorrect. There are situations where we expect that the view element will not be converted: for example when text is wrong with schema. On the other hand we have "default" converters which will take care of "non-intentionally not-converted elements". So yeah, this should be removed.

@scofalik
Copy link
Contributor Author

I fixed unneeded warning and fixed merge message.

@scofalik
Copy link
Contributor Author

The build failed but tests are fine:

No output has been received in the last 10m0s (...)
The build has been terminated

// 3. Extract children from document fragments to flatten results.
const convertedChildren = viewChildren
.map( ( viewChild ) => this._convertItem( viewChild, consumable, additionalData ) )
.filter( ( converted ) => converted instanceof ModelNode || converted instanceof ModelDocumentFragment )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is like a black hole. Can't we just throw here? Or at least warn the developer. But I think that throwing is better because this isn't even a runtime error but simply a serious implementation bug. The same applies to _convertItem() – I feel that we could throw there as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, _convertChildren() uses _convertItem() so the "wrong results" are not really wrong but just "non-convertable content". You can change the comment and it will be fine.

@Reinmar
Copy link
Member

Reinmar commented Apr 25, 2017

I commented on one issue.

// Flatten and remove nulls.
return convertedChildren.reduce( ( a, b ) => b ? a.concat( b ) : a, [] );
// 1. Map those children to model.
// 2. Filter out wrong results.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad @scofalik cause bad comment!

*/
log.warn( 'view-conversion-dispatcher-incorrect-result: Dropped incorrect conversion result.', [ input, data.output ] );

data.output = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe return null?


// Silences warnings that pop up in tests. Use when the test checks a specific functionality and we are not interested in those logs.
// No need to restore `log.warn` - it is done in `afterEach()`.
function silenceWarnings() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure but I'm afraid that this may silence too many warnings as log may be defined just once at the beginning of this file. And if we ever switch to bundling all test files into one module (to improve Webpack's performance) this will silence all logs forever.

Copy link
Contributor Author

@scofalik scofalik Apr 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? log.warn is restored in afterEach(). Anyway, I am fine with having those warnings as long as you are.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I haven't noticed that. :*

@scofalik
Copy link
Contributor Author

I pushed one more commit. You, again, start being PicKy...

@Reinmar Reinmar merged commit 16ae05a into master Apr 25, 2017
@Reinmar Reinmar deleted the t/932 branch April 25, 2017 13:40
@Reinmar Reinmar changed the title ViewConverterBuilder#toAttribute now passes model.DocumentFragment to data.output if was converter from view element. Unify values returned in data.output during view-to-model conversion Apr 25, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
2 participants