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

fix(compiler): invalid metadata used in decorator index #88

Merged
merged 1 commit into from
Feb 13, 2018

Conversation

yungcheng
Copy link
Contributor

@yungcheng yungcheng commented Feb 9, 2018

Details

Addressing discussion here I believe it should've been state.file.metadata

Does this PR introduce a breaking change?

  • Yes
  • No

@salesforce-best-lwc-internal
Copy link

Benchmark comparison

Base commit: 99e4b24 | Target commit: 1b18bef

benchmark base(99e4b24) target(1b18bef) trend
append-1k.benchmark:benchmark-table-component/append/1k 316.01 (± 4.53 ms) 354.89 (± 6.90 ms) 👎
clear-1k.benchmark:benchmark-table/clear/1k 29.89 (± 1.06 ms) 34.11 (± 1.99 ms) 👎
create-10k.benchmark:benchmark-table-component/create/10k 2012.15 (± 26.00 ms) 2088.57 (± 23.03 ms) 👎
create-1k.benchmark:benchmark-table-component/create/1k 217.38 (± 2.40 ms) 252.57 (± 17.81 ms) 👎
update-10th-1k.benchmark:benchmark-table-component/update-10th/1k 131.78 (± 1.82 ms) 134.59 (± 4.38 ms) 👎

Copy link
Collaborator

@apapko apapko left a comment

Choose a reason for hiding this comment

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

The metadata merge fix looks good; however, i'm concerned with not handling metadata for multiple classes - in the event of component class not being processed last, we may endup without metadata, which will cause issues.
We definitely need your metadata merge fix and as for the multiple classes, we need to open an issue.

@@ -420,7 +420,16 @@ describe('metadata', () => {
declarationLoc: {
end: { column: 1, line: 13 },
start: { column: 0, line: 3 }
}
},
marked: [],
Copy link
Member

Choose a reason for hiding this comment

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

What is marked ?

},
marked: [],
modules: {
exports: { exported: ['Foo'], specifiers: [{ exported: "default", kind: "local", local: "Foo" }] },
Copy link
Member

Choose a reason for hiding this comment

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

What is kind and local used for ?

Copy link
Contributor

Choose a reason for hiding this comment

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

kind is the type of export, and local is the local binding when type is local. this sounds a lot like the metadata of modules provided out of the box from babel/rollup.

{ imported: ['Element'], source: 'engine', specifiers: [{ imported: 'Element', kind: 'named', local: 'Element' }] }
]
},
usedHelpers: []
Copy link
Member

Choose a reason for hiding this comment

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

What is usedHelpers for ?

modules: {
exports: { exported: ['Foo'], specifiers: [{ exported: "default", kind: "local", local: "Foo" }] },
imports: [
{ imported: ['api'], source: 'engine', specifiers: [{ imported: 'api', kind: 'named', local: 'api' }] },
Copy link
Member

Choose a reason for hiding this comment

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

Why do you keep track of imported and specifiers independently?

modules: {
exports: { exported: ['Foo'], specifiers: [{ exported: "default", kind: "local", local: "Foo" }] },
imports: [
{ imported: ['api'], source: 'engine', specifiers: [{ imported: 'api', kind: 'named', local: 'api' }] },
Copy link
Member

Choose a reason for hiding this comment

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

What is local used for?

@pmdartus pmdartus mentioned this pull request Feb 12, 2018
2 tasks
Copy link
Member

@pmdartus pmdartus left a comment

Choose a reason for hiding this comment

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

As discussed this morning with @yungcheng and @apapko, we will stop using state.file.metadata to store the metadata:

  • it's a private / not documented API from babel and it will probably break in the future.
  • mutating this object can have unexpected side effects on other plugins.

We have agreed that we will rely on plugin config to communicate the metadata to the plugin consumer.

import { transform } from 'babel-core';
import raptorClassTransformPlugin from 'babel-plugin-transform-lwc-class';

const metadata = {};

const { code } = transform(code, {
    plugins: [
        [
            raptorClassTransformPlugin,
            {
                metadata,
            },
        ],
    ],
});

// The metadata object get populated by the plugin.
console.log(code, metadata)

FYI @rsalvador.

@salesforce-best-lwc-internal
Copy link

Benchmark comparison

Base commit: c321b1d | Target commit: c5338ec

benchmark base(c321b1d) target(c5338ec) trend
table-append-1k.benchmark:benchmark-table/append/1k 257.48 (± 5.92 ms) 249.53 (± 6.47 ms) 👍
table-clear-1k.benchmark:benchmark-table/clear/1k 13.98 (± 0.48 ms) 12.94 (± 0.48 ms) 👍
table-create-10k.benchmark:benchmark-table/create/10k 1464.95 (± 20.97 ms) 1404.92 (± 8.24 ms) 👍
table-create-1k.benchmark:benchmark-table/create/1k 156.84 (± 4.50 ms) 153.56 (± 3.06 ms) 👍
table-update-10th-1k.benchmark:benchmark-table/update-10th/1k 146.55 (± 4.30 ms) 143.31 (± 3.75 ms) 👌
tablecmp-append-1k.benchmark:benchmark-table-component/append/1k 335.02 (± 17.48 ms) 316.73 (± 6.56 ms) 👍
tablecmp-clear-1k.benchmark:benchmark-table/clear/1k 37.74 (± 2.86 ms) 30.47 (± 1.47 ms) 👍
tablecmp-create-10k.benchmark:benchmark-table-component/create/10k 2152.66 (± 62.84 ms) 2037.89 (± 22.42 ms) 👍
tablecmp-create-1k.benchmark:benchmark-table-component/create/1k 236.45 (± 6.68 ms) 224.97 (± 3.01 ms) 👍
tablecmp-update-10th-1k.benchmark:benchmark-table-component/update-10th/1k 140.03 (± 7.03 ms) 129.89 (± 2.85 ms) 👍

@salesforce-best-lwc-internal
Copy link

Benchmark comparison

Base commit: c321b1d | Target commit: b5b5baf

benchmark base(c321b1d) target(b5b5baf) trend
table-append-1k.benchmark:benchmark-table/append/1k 257.48 (± 5.92 ms) 248.48 (± 5.57 ms) 👍
table-clear-1k.benchmark:benchmark-table/clear/1k 13.98 (± 0.48 ms) 12.78 (± 0.40 ms) 👍
table-create-10k.benchmark:benchmark-table/create/10k 1464.95 (± 20.97 ms) 1376.57 (± 12.19 ms) 👍
table-create-1k.benchmark:benchmark-table/create/1k 156.84 (± 4.50 ms) 143.68 (± 1.29 ms) 👍
table-update-10th-1k.benchmark:benchmark-table/update-10th/1k 146.55 (± 4.30 ms) 138.90 (± 3.93 ms) 👍
tablecmp-append-1k.benchmark:benchmark-table-component/append/1k 335.02 (± 17.48 ms) 319.09 (± 6.85 ms) 👍
tablecmp-clear-1k.benchmark:benchmark-table/clear/1k 37.74 (± 2.86 ms) 32.56 (± 1.29 ms) 👍
tablecmp-create-10k.benchmark:benchmark-table-component/create/10k 2152.66 (± 62.84 ms) 2052.07 (± 19.90 ms) 👍
tablecmp-create-1k.benchmark:benchmark-table-component/create/1k 236.45 (± 6.68 ms) 227.35 (± 3.05 ms) 👍
tablecmp-update-10th-1k.benchmark:benchmark-table-component/update-10th/1k 140.03 (± 7.03 ms) 133.30 (± 2.62 ms) 👍

Copy link
Collaborator

@apapko apapko left a comment

Choose a reason for hiding this comment

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

Few question on the PR. Other than that, i don't know of an alternative way to carry metadata around. Perhaps PM will have more input

@@ -29,16 +29,19 @@ module.exports = function ({ types: t }) {
const classBody = path.get('body');

if (isDefaultExport(path)) {
const hasMetadata = this.opts && this.opts.hasOwnProperty('metadata');
const declaration = path.parentPath.node;
if (declaration.leadingComments) {
const lastComment = declaration.leadingComments[declaration.leadingComments.length - 1].value;
Copy link
Collaborator

Choose a reason for hiding this comment

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

can declaration leading comments be 0 length? Just curios if we can hit out of bound index

@@ -140,7 +141,9 @@ module.exports = function decoratorVisitor({ types: t }) {
// Note: In the (extremely rare) case of multiple classes in the same file, only the metadata about the
// last class will be returned
const metadata = transform(t, klass, decorators);
state.file.metadata = Object.assign({}, state.metadata, metadata);
if (hasMetadata) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it safe to assume that if metadata has been provided during plugins initialization ( line 11 of javascript.js ), then it will always appear in this.opts?

@@ -140,7 +141,9 @@ module.exports = function decoratorVisitor({ types: t }) {
// Note: In the (extremely rare) case of multiple classes in the same file, only the metadata about the
// last class will be returned
const metadata = transform(t, klass, decorators);
state.file.metadata = Object.assign({}, state.metadata, metadata);
if (hasMetadata) {
this.opts.metadata = Object.assign({}, this.opts.metadata, metadata);
Copy link
Collaborator

Choose a reason for hiding this comment

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

since we have better control of metadata format here, should we attempt to map metadata to a classname? Or have a list of metadata objects - one per classname? I'm just thinking about your comment above, it could bite us

const declaration = path.parentPath.node;
if (declaration.leadingComments) {
const lastComment = declaration.leadingComments[declaration.leadingComments.length - 1].value;
const sanitized = sanitizeComment(lastComment);
if (sanitized) {
state.file.metadata.doc = sanitized;
if (sanitized && hasMetadata) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

sanitizeComment function declaration needs param existence check prior invoking trim()

@@ -19,6 +19,6 @@ export default function(code, options) {
return {
code: transformed.code,
map: transformed.map,
metadata: transformed.metadata,
metadata: transformed.options.plugins[0][1].metadata
Copy link
Collaborator

Choose a reason for hiding this comment

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

is plugins order always preserved?

@pmdartus
Copy link
Member

After going through the babel issues, it appears that they want to enforce aggressive caching for plugin config (babel/babel#6326, babel/babel#6350). Even if I dislike it, using the state.file is the safest solution that we have for now. @yungcheng could you revert the changes?

Before merging the PR, we should also create an issue to fix that in the future.

@salesforce-best-lwc-internal
Copy link

Benchmark comparison

Base commit: c321b1d | Target commit: 24769fe

benchmark base(c321b1d) target(24769fe) trend
table-append-1k.benchmark:benchmark-table/append/1k 257.48 (± 5.92 ms) 251.53 (± 2.44 ms) 👍
table-clear-1k.benchmark:benchmark-table/clear/1k 13.98 (± 0.48 ms) 12.51 (± 0.44 ms) 👍
table-create-10k.benchmark:benchmark-table/create/10k 1464.95 (± 20.97 ms) 1392.14 (± 17.85 ms) 👍
table-create-1k.benchmark:benchmark-table/create/1k 156.84 (± 4.50 ms) 144.71 (± 1.98 ms) 👍
table-update-10th-1k.benchmark:benchmark-table/update-10th/1k 146.55 (± 4.30 ms) 139.84 (± 2.25 ms) 👍
tablecmp-append-1k.benchmark:benchmark-table-component/append/1k 335.02 (± 17.48 ms) 309.95 (± 5.36 ms) 👍
tablecmp-clear-1k.benchmark:benchmark-table/clear/1k 37.74 (± 2.86 ms) 31.41 (± 1.62 ms) 👍
tablecmp-create-10k.benchmark:benchmark-table-component/create/10k 2152.66 (± 62.84 ms) 2031.03 (± 25.95 ms) 👍
tablecmp-create-1k.benchmark:benchmark-table-component/create/1k 236.45 (± 6.68 ms) 228.00 (± 4.68 ms) 👍
tablecmp-update-10th-1k.benchmark:benchmark-table-component/update-10th/1k 140.03 (± 7.03 ms) 132.90 (± 1.74 ms) 👍

Copy link
Member

@pmdartus pmdartus left a comment

Choose a reason for hiding this comment

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

We don't have a better solution for now in terms of surfacing the metadata.

@yungcheng LGTM, to unblock us for now. Can you open to track the cleanup work that we need to do?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants