@lwc/babel-plugin-component
Advanced tools
Comparing version 0.35.5 to 0.35.6-alpha1
{ | ||
"name": "@lwc/babel-plugin-component", | ||
"description": "Babel plugin to transform a LWC module", | ||
"version": "0.35.5", | ||
"version": "0.35.6-alpha1", | ||
"main": "src/index.js", | ||
@@ -14,3 +14,3 @@ "typings": "types/index.d.ts", | ||
"@babel/plugin-proposal-class-properties": "7.1.0", | ||
"@lwc/errors": "0.35.5" | ||
"@lwc/errors": "0.35.6-alpha1" | ||
}, | ||
@@ -23,3 +23,3 @@ "devDependencies": { | ||
}, | ||
"gitHead": "82669bbe935aee21c590753667c60f16ffa0cf7e" | ||
"gitHead": "5aa40c386dfdac48b9db4afb7a7c5711b81ebc3a" | ||
} |
@@ -618,201 +618,1 @@ /* | ||
} | ||
describe('Metadata', () => { | ||
apiValueMetadataTest( | ||
'gather metadata for static "string" property value', | ||
`@api staticString = "string value";`, | ||
{ | ||
type: "property", | ||
name: "staticString", | ||
loc: { | ||
end: { line: 2, column: 87 }, | ||
start: { line: 2, column: 52 }, | ||
}, | ||
decorator: "api", | ||
value: { type: "string", value:"string value" }, | ||
}, | ||
); | ||
apiValueMetadataTest( | ||
'gather metadata for static "boolean" property value', | ||
`@api staticBoolean = false;`, | ||
{ | ||
type: "property", | ||
name: "staticBoolean", | ||
loc: { | ||
end: { line: 2, column: 79 }, | ||
start: { line: 2, column: 52 }, | ||
}, | ||
decorator: "api", | ||
value: { type: "boolean", value: false }, | ||
}, | ||
); | ||
apiValueMetadataTest( | ||
'gather metadata for static "numeric" property value', | ||
`@api numeric = 0;`, | ||
{ | ||
decorator: "api", | ||
loc: { | ||
end: { column: 69, line: 2 }, | ||
start: { column: 52, line: 2 }, | ||
}, | ||
name: "numeric", | ||
type: "property", | ||
value: { type: "number", value: 0 } | ||
}, | ||
); | ||
apiValueMetadataTest( | ||
'gather metadata for static property without value', | ||
`@api nodefault`, | ||
{ | ||
decorator: "api", | ||
loc: { | ||
end: { column: 66, line: 2 }, | ||
start: { column: 52, line: 2 }, | ||
}, | ||
name: "nodefault", | ||
type: "property", | ||
value: { type: "unresolved", value: undefined } | ||
}, | ||
); | ||
apiValueMetadataTest( | ||
'gather metadata for static property with "undefined" value', | ||
`@api staticUndefined = undefined;`, | ||
{ | ||
decorator: "api", | ||
loc: { | ||
end: { column: 85, line: 2 }, | ||
start: { column: 52, line: 2 }, | ||
}, | ||
name: "staticUndefined", | ||
type: "property", | ||
value: { type: "unresolved", value: undefined } | ||
}, | ||
); | ||
apiValueMetadataTest( | ||
'gather metadata for static property with "null" value', | ||
`@api staticNull = null;`, | ||
{ | ||
decorator: "api", | ||
loc: { | ||
end: { column: 75, line: 2 }, | ||
start: { column: 52, line: 2 }, | ||
}, | ||
name: "staticNull", | ||
type: "property", | ||
value: { type: "null", value: null } | ||
}, | ||
); | ||
apiValueMetadataTest( | ||
'gather metadata for static property with "object" value', | ||
`@api staticObject = { | ||
stringProp: "string property", | ||
numericProp: 0, | ||
booleanProp: true, | ||
arrayProp: [], | ||
objectProp: {}, | ||
};`, | ||
{ | ||
decorator: "api", | ||
loc: { | ||
end: { column: 2, line: 8 }, | ||
start: { column: 52, line: 2 }, | ||
}, | ||
name: "staticObject", | ||
type: "property", | ||
value: { | ||
type: "object", | ||
value: { | ||
stringProp: { | ||
type: "string", | ||
value: "string property", | ||
}, | ||
numericProp: { | ||
type: "number", | ||
value: 0, | ||
}, | ||
booleanProp: { | ||
type: "boolean", | ||
value: true, | ||
}, | ||
arrayProp: { | ||
type: "array", | ||
value: [], | ||
}, | ||
objectProp: { | ||
type: "object", | ||
value: {}, | ||
}, | ||
} | ||
}, | ||
}, | ||
); | ||
apiValueMetadataTest( | ||
'gather metadata for static property with "array" value', | ||
`@api staticArray = ['stringval', 0, true, null, undefined, {}, []];;`, | ||
{ | ||
decorator: "api", | ||
loc: { | ||
end: { column: 119, line: 2 }, | ||
start: { column: 52, line: 2 }, | ||
}, | ||
name: "staticArray", | ||
type: "property", | ||
value: { | ||
type: "array", | ||
value: [ | ||
{ type: "string", value: "stringval" }, | ||
{ type: "number", value: 0 }, | ||
{ type: "boolean", value: true }, | ||
{ type: "null", value: null }, | ||
{ type: "unresolved", value: undefined }, | ||
{ type: "object", value: {} }, | ||
{ type: "array", value: [] }, | ||
] | ||
} | ||
}, | ||
); | ||
pluginTest( | ||
'does not gather metadata value for public setter and getter methods', | ||
` | ||
import { LightningElement, api } from 'lwc'; | ||
export default class Foo extends LightningElement { | ||
_privateTodo; | ||
get todo () { return this._privateTodo; } | ||
@api set todo (val) { return this._privateTodo = val; } | ||
} | ||
`, | ||
{ | ||
output: { | ||
metadata: { | ||
classMembers: [ | ||
{ | ||
decorator: "api", | ||
loc: { | ||
end: { column: 55, line: 5 }, | ||
start: { column: 0, line: 5 } | ||
}, | ||
name: "todo", | ||
type: "property" | ||
} | ||
], | ||
declarationLoc: { | ||
end: { column: 1, line: 6 }, | ||
start: { column: 0, line: 2 } | ||
}, | ||
decorators: [ | ||
{ targets: [{ name: "todo", type: "property" }], type: "api" } | ||
], | ||
exports: [{ type: "ExportDefaultDeclaration" }] | ||
} | ||
} | ||
} | ||
); | ||
}); |
@@ -180,341 +180,1 @@ /* | ||
}); | ||
describe('metadata', () => { | ||
pluginTest('class jsdoc single line (and declarationLoc)', ` | ||
import { LightningElement } from 'lwc'; | ||
/** Foo doc */ | ||
export default class Foo extends LightningElement { | ||
} | ||
`, { | ||
output: { | ||
metadata: { | ||
decorators: [], | ||
classMembers: [], | ||
declarationLoc: { start: { line: 3, column: 0 }, end: { line: 4, column: 1 }}, | ||
doc: '* Foo doc', | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
} | ||
} | ||
}); | ||
pluginTest('class jsdoc', ` | ||
import { LightningElement } from 'lwc'; | ||
/** | ||
* Foo doc | ||
*/ | ||
export default class Foo extends LightningElement { | ||
} | ||
`, { | ||
output: { | ||
metadata: { | ||
decorators: [], | ||
classMembers: [], | ||
declarationLoc: { end: { column: 1, line: 6 }, start: { column: 0, line: 5 } }, | ||
doc: "*\n* Foo doc", | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
} | ||
} | ||
}); | ||
pluginTest('class jsdoc multiline', ` | ||
import { LightningElement } from 'lwc'; | ||
/** | ||
* multi | ||
* line | ||
*/ | ||
export default class Foo extends LightningElement { | ||
} | ||
`, { | ||
output: { | ||
metadata: { | ||
decorators: [], | ||
classMembers: [], | ||
declarationLoc: { end: { column: 1, line: 7 }, start: { column: 0, line: 6 } }, | ||
doc: '*\n* multi\n* line', | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
} | ||
} | ||
}); | ||
pluginTest('class jsdoc multi comments', ` | ||
import { LightningElement } from 'lwc'; | ||
/** first */ | ||
/** last */ | ||
export default class Foo extends LightningElement { | ||
} | ||
`, { | ||
output: { | ||
metadata: { | ||
decorators: [], | ||
classMembers: [], | ||
declarationLoc: { end: { column: 1, line: 5 }, start: { column: 0, line: 4 } }, | ||
doc: "* last", | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
}, | ||
} | ||
}); | ||
pluginTest('class jsdoc empty', ` | ||
import { LightningElement } from 'lwc'; | ||
/** */ | ||
export default class Foo extends LightningElement { | ||
} | ||
`, { | ||
output: { | ||
metadata: { | ||
decorators: [], | ||
classMembers: [], | ||
doc: "*", | ||
declarationLoc: { | ||
end: { column: 1, line: 4 }, | ||
start: { column: 0, line: 3 } | ||
}, | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
} | ||
} | ||
}); | ||
pluginTest('class no-jsdoc /**/', ` | ||
import { LightningElement } from 'lwc'; | ||
/* not a jsdoc */ | ||
export default class Foo extends LightningElement { | ||
} | ||
`, { | ||
output: { | ||
metadata: { | ||
decorators: [], | ||
classMembers: [], | ||
declarationLoc: { | ||
end: { column: 1, line: 4 }, | ||
start: { column: 0, line: 3 } | ||
}, | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
} | ||
} | ||
}); | ||
pluginTest('class no-jsdoc //', ` | ||
import { LightningElement } from 'lwc'; | ||
// not a jsdoc | ||
export default class Foo extends LightningElement { | ||
} | ||
`, { | ||
output: { | ||
metadata: { | ||
decorators: [], | ||
classMembers: [], | ||
declarationLoc: { | ||
end: { column: 1, line: 4 }, | ||
start: { column: 0, line: 3 } | ||
}, | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
} | ||
} | ||
}); | ||
pluginTest('json in comment', ` | ||
import { LightningElement } from 'lwc'; | ||
/** { one: "1", two: '2', array: [1, 2, 3]} */ | ||
export default class Foo extends LightningElement { | ||
} | ||
`, { | ||
output: { | ||
metadata: { | ||
decorators: [], | ||
classMembers: [], | ||
declarationLoc: { | ||
end: { column: 1, line: 4 }, | ||
start: { column: 0, line: 3 } | ||
}, | ||
doc: "* { one: \"1\", two: '2', array: [1, 2, 3]}", | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
} | ||
} | ||
}); | ||
pluginTest( | ||
"tooling metadata", | ||
` | ||
import { LightningElement, api, track } from 'lwc'; | ||
// not a jsdoc | ||
export default class Foo extends LightningElement { | ||
@track state; | ||
/** property-comment */ @api publicProp; | ||
/** method-comment */ @api publicMethod() {} | ||
privateProp; | ||
privateMethod() {} | ||
_privateTodo; | ||
@api | ||
get todo () {return this._privateTodo;} | ||
set todo (val) {return this._privateTodo = val;} | ||
} | ||
`, | ||
{ | ||
output: { | ||
metadata: { | ||
decorators: [ | ||
{ | ||
type: "api", | ||
targets: [ | ||
{ type: "property", name: "publicProp", value: { type: "unresolved", value: undefined } }, | ||
{ type: "property", name: "todo" }, | ||
{ type: "method", name: "publicMethod" } | ||
] | ||
}, | ||
{ | ||
type: "track", | ||
targets: [ | ||
{ type: "property", name: "state" } | ||
] | ||
} | ||
], | ||
classMembers: [ | ||
{ | ||
type: "property", | ||
name: "state", | ||
loc: { | ||
start: { line: 4, column: 0 }, | ||
end: { line: 4, column: 13 } | ||
}, | ||
decorator: "track" | ||
}, | ||
{ | ||
type: "property", | ||
name: "publicProp", | ||
value: { type: "unresolved", value: undefined }, | ||
loc: { | ||
start: { line: 5, column: 24 }, | ||
end: { line: 5, column: 40 } | ||
}, | ||
doc: "* property-comment", | ||
decorator: "api" | ||
}, | ||
{ | ||
type: "method", | ||
name: "publicMethod", | ||
loc: { | ||
start: { line: 6, column: 22 }, | ||
end: { line: 6, column: 44 } | ||
}, | ||
doc: "* method-comment", | ||
decorator: "api" | ||
}, | ||
{ | ||
type: "property", | ||
name: "privateProp", | ||
loc: { | ||
start: { line: 7, column: 0 }, | ||
end: { line: 7, column: 12 } | ||
} | ||
}, | ||
{ | ||
type: "method", | ||
name: "privateMethod", | ||
loc: { | ||
start: { line: 8, column: 0 }, | ||
end: { line: 8, column: 18 } | ||
} | ||
}, | ||
{ | ||
type: "property", | ||
name: "todo", | ||
loc: { | ||
start: { line: 10, column: 0 }, | ||
end: { line: 11, column: 39 } | ||
}, | ||
decorator: "api" | ||
} | ||
], | ||
declarationLoc: { | ||
start: { line: 3, column: 0 }, | ||
end: { line: 13, column: 1 } | ||
}, | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
} | ||
} | ||
} | ||
); | ||
pluginTest( | ||
"@api on getter only", | ||
` | ||
import { LightningElement, api} from 'lwc'; | ||
export default class Foo extends LightningElement { | ||
@api | ||
get todo () {return this._privateTodo;} | ||
set todo (val) {return this._privateTodo = val;} | ||
} | ||
`, | ||
{ | ||
output: { | ||
metadata: { | ||
decorators: [ | ||
{ | ||
type: "api", | ||
targets: [ | ||
{ type: "property", name: "todo" }, | ||
] | ||
} | ||
], | ||
classMembers: [ | ||
{ | ||
type: "property", | ||
name: "todo", | ||
loc: { | ||
start: { line: 3, column: 0 }, | ||
end: { line: 4, column: 39 } | ||
}, | ||
decorator: "api" | ||
} | ||
], | ||
declarationLoc: { | ||
start: { line: 2, column: 0 }, | ||
end: { line: 6, column: 1 } | ||
}, | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
} | ||
} | ||
} | ||
); | ||
pluginTest( | ||
"@api on getter only without a setter pair", | ||
` | ||
import { LightningElement, api} from 'lwc'; | ||
export default class Foo extends LightningElement { | ||
@api | ||
get todo () {return this._privateTodo;} | ||
} | ||
`, | ||
{ | ||
output: { | ||
metadata: { | ||
decorators: [ | ||
{ | ||
type: "api", | ||
targets: [ | ||
{ type: "property", name: "todo" }, | ||
] | ||
} | ||
], | ||
classMembers: [ | ||
{ | ||
type: "property", | ||
name: "todo", | ||
loc: { | ||
start: { line: 3, column: 0 }, | ||
end: { line: 4, column: 39 } | ||
}, | ||
decorator: "api" | ||
} | ||
], | ||
declarationLoc: { | ||
start: { line: 2, column: 0 }, | ||
end: { line: 5, column: 1 } | ||
}, | ||
exports: [{ type: 'ExportDefaultDeclaration' }], | ||
} | ||
} | ||
} | ||
); | ||
}); |
@@ -23,3 +23,3 @@ /* | ||
import { registerComponent as _registerComponent } from "lwc"; | ||
class Test { | ||
@@ -30,3 +30,3 @@ constructor() { | ||
} | ||
_registerDecorators(Test, { | ||
@@ -37,3 +37,3 @@ track: { | ||
}); | ||
export default _registerComponent(Test, { | ||
@@ -59,3 +59,3 @@ tmpl: _tmpl | ||
import { registerComponent as _registerComponent } from "lwc"; | ||
class Test { | ||
@@ -68,3 +68,3 @@ constructor() { | ||
} | ||
_registerDecorators(Test, { | ||
@@ -75,3 +75,3 @@ track: { | ||
}); | ||
export default _registerComponent(Test, { | ||
@@ -140,45 +140,1 @@ tmpl: _tmpl | ||
}); | ||
describe('Metadata', () => { | ||
pluginTest( | ||
'gather metadata', | ||
` | ||
import { LightningElement, track } from 'lwc'; | ||
export default class Test extends LightningElement { | ||
@track state; | ||
} | ||
`, | ||
{ | ||
output: { | ||
metadata: { | ||
decorators: [ | ||
{ | ||
type: "track", | ||
targets: [{ name: "state", type: "property" }] | ||
} | ||
], | ||
classMembers: [ | ||
{ | ||
type: "property", | ||
name: "state", | ||
loc: { | ||
start: { line: 3, column: 0 }, | ||
end: { line: 3, column: 13 } | ||
}, | ||
decorator: "track" | ||
} | ||
], | ||
declarationLoc: { | ||
end: { column: 1, line: 4 }, | ||
start: { column: 0, line: 2 } | ||
}, | ||
exports: [ | ||
{ | ||
type: 'ExportDefaultDeclaration', | ||
} | ||
], | ||
} | ||
} | ||
} | ||
); | ||
}); |
@@ -60,5 +60,2 @@ /* | ||
} | ||
if (expected.output.metadata) { | ||
expect(output.metadata).toEqual(expected.output.metadata); | ||
} | ||
} else { | ||
@@ -65,0 +62,0 @@ throw new TypeError(`Transform test expect an object with either error or output.`); |
@@ -9,41 +9,2 @@ /* | ||
const wireMetadataParameterTest = | ||
(testName, {declaration = '', wireParameters = '', expectedStaticParameters = {}, expectedVariableParameters = {}}) => { | ||
pluginTest( | ||
testName, | ||
` | ||
import { wire } from 'lwc'; | ||
import { getRecord } from 'recordDataService'; | ||
${declaration}; | ||
export default class Test { | ||
@wire(getRecord, { ${wireParameters.join(',')} }) | ||
recordData; | ||
} | ||
`, | ||
{ | ||
output: { | ||
metadata: { | ||
decorators: [{ | ||
type: 'wire', | ||
targets: [ | ||
{ | ||
adapter: { name: 'getRecord', reference: 'recordDataService' }, | ||
name: 'recordData', | ||
params: expectedVariableParameters, | ||
static: expectedStaticParameters , | ||
type: 'property', | ||
} | ||
], | ||
}], | ||
exports: [ | ||
{ | ||
type: 'ExportDefaultDeclaration', | ||
} | ||
], | ||
}, | ||
}, | ||
}, | ||
); | ||
}; | ||
describe('Transform property', () => { | ||
@@ -64,3 +25,3 @@ pluginTest('transforms wired field', ` | ||
import { getFoo } from "data-service"; | ||
class Test { | ||
@@ -71,3 +32,3 @@ constructor() { | ||
} | ||
_registerDecorators(Test, { | ||
@@ -86,3 +47,3 @@ wire: { | ||
}); | ||
export default _registerComponent(Test, { | ||
@@ -109,3 +70,3 @@ tmpl: _tmpl | ||
import { getFoo } from "data-service"; | ||
class Test { | ||
@@ -116,3 +77,3 @@ constructor() { | ||
} | ||
_registerDecorators(Test, { | ||
@@ -133,3 +94,3 @@ wire: { | ||
}); | ||
export default _registerComponent(Test, { | ||
@@ -170,3 +131,3 @@ tmpl: _tmpl | ||
import { getFoo } from "data-service"; | ||
class Test { | ||
@@ -177,3 +138,3 @@ constructor() { | ||
} | ||
_registerDecorators(Test, { | ||
@@ -188,3 +149,3 @@ wire: { | ||
}); | ||
export default _registerComponent(Test, { | ||
@@ -210,3 +171,3 @@ tmpl: _tmpl | ||
import getFoo from "foo"; | ||
class Test { | ||
@@ -217,3 +178,3 @@ constructor() { | ||
} | ||
_registerDecorators(Test, { | ||
@@ -228,3 +189,3 @@ wire: { | ||
}); | ||
export default _registerComponent(Test, { | ||
@@ -250,3 +211,3 @@ tmpl: _tmpl | ||
import { getFoo } from "data-service"; | ||
class Test { | ||
@@ -257,3 +218,3 @@ constructor() { | ||
} | ||
_registerDecorators(Test, { | ||
@@ -266,3 +227,3 @@ wire: { | ||
}); | ||
export default _registerComponent(Test, { | ||
@@ -377,3 +338,3 @@ tmpl: _tmpl | ||
import { getFoo } from "data-service"; | ||
class Test { | ||
@@ -385,3 +346,3 @@ constructor() { | ||
} | ||
_registerDecorators(Test, { | ||
@@ -409,3 +370,3 @@ wire: { | ||
}); | ||
export default _registerComponent(Test, { | ||
@@ -434,7 +395,7 @@ tmpl: _tmpl | ||
import { getFoo } from "data-service"; | ||
class Test { | ||
wiredMethod() {} | ||
} | ||
_registerDecorators(Test, { | ||
@@ -454,3 +415,3 @@ wire: { | ||
}); | ||
export default _registerComponent(Test, { | ||
@@ -481,133 +442,1 @@ tmpl: _tmpl | ||
}); | ||
describe('Metadata', () => { | ||
pluginTest( | ||
'gather wire metadata', | ||
` | ||
import { wire } from 'lwc'; | ||
import { getFoo } from 'data-service'; | ||
export default class Test { | ||
@wire(getFoo, { key1: "$prop1", key2: ["fixed"]}) | ||
wiredProp; | ||
@wire(getFoo, { key1: "$prop1", key2: ["fixed"]}) | ||
wiredMethod() {} | ||
} | ||
`, | ||
{ | ||
output: { | ||
metadata: { | ||
decorators: [{ | ||
type: 'wire', | ||
targets: [{ | ||
adapter: { name: 'getFoo', reference: 'data-service' }, | ||
name: 'wiredProp', | ||
params: { key1: 'prop1' }, | ||
static: { key2: { value: ['fixed'], type: 'array' } }, | ||
type: 'property', | ||
}, | ||
{ | ||
adapter: { name: 'getFoo', reference: 'data-service' }, | ||
name: 'wiredMethod', | ||
params: { key1: 'prop1' }, | ||
static: { key2: { value: ['fixed'], type: 'array' } }, | ||
type: 'method', | ||
}], | ||
}], | ||
exports: [ | ||
{ | ||
type: 'ExportDefaultDeclaration', | ||
} | ||
], | ||
}, | ||
}, | ||
}, | ||
); | ||
wireMetadataParameterTest('when constant initialised to a string-literal should extract the value', | ||
{ declaration: `const stringConstant = '123';`, | ||
wireParameters: ['userId: stringConstant'], | ||
expectedStaticParameters: { userId: { value: '123', type: 'string'} } }); | ||
wireMetadataParameterTest('when constant initialised to a number-literal should extract the value', | ||
{ declaration: `const numberConstant = 100;`, | ||
wireParameters: ['size: numberConstant'], | ||
expectedStaticParameters: { size: { value: 100, type: 'number'} } }); | ||
wireMetadataParameterTest('when constant initialised to a boolean-literal should extract the value', | ||
{ declaration: `const booleanConstant = true;`, | ||
wireParameters: ['isRegistered: booleanConstant'], | ||
expectedStaticParameters: { isRegistered: { value: true, type: 'boolean'} } }); | ||
wireMetadataParameterTest('when constant initialised as a reference to another should mark as unresolved', | ||
{ declaration: `const stringConstant = '123'; const referenceConstant = stringConstant;`, | ||
wireParameters: ['recordId: referenceConstant'], | ||
expectedStaticParameters: { recordId: { type: 'unresolved', value: 'identifier' } } }); | ||
wireMetadataParameterTest('when importing a default export from a module should reference the name of the module', | ||
{ declaration: `import id from '@salesforce/user/Id';`, | ||
wireParameters: ['recordId: id'], | ||
expectedStaticParameters: { recordId: { value: '@salesforce/user/Id', type: 'module' } } }); | ||
wireMetadataParameterTest('when parameter reference missing should mark as unresolved', | ||
{ wireParameters: ['recordId: id'], | ||
expectedStaticParameters: { recordId: { type: 'unresolved', value: 'identifier'} } }); | ||
wireMetadataParameterTest('when importing named export with "as" from a module should reference the name of the module', | ||
{ declaration: `import { id as currentUserId } from '@salesforce/user/Id';`, | ||
wireParameters: ['recordId: currentUserId'], | ||
expectedStaticParameters: { recordId: { value: '@salesforce/user/Id', type: 'module' } } }); | ||
wireMetadataParameterTest('when importing a named export from a module should reference the name of the module', | ||
{ declaration: `import { id } from '@salesforce/user/Id';`, | ||
wireParameters: ['recordId: id'], | ||
expectedStaticParameters: { recordId: { value: '@salesforce/user/Id', type: 'module' } } }); | ||
wireMetadataParameterTest('when importing from a relative module should reference the name of the module', | ||
{ declaration: `import id from './someReference.js';`, | ||
wireParameters: ['recordId: id'], | ||
expectedStaticParameters: { recordId: { value: './someReference.js', type: 'module' } } }); | ||
wireMetadataParameterTest('when referencing a "let" variable should mark as unresolved', | ||
{ declaration: `let userId = '123';`, | ||
wireParameters: ['recordId: userId'], | ||
expectedStaticParameters: { recordId: { type: 'unresolved', value: 'identifier'} } }); | ||
wireMetadataParameterTest('when referencing a member expression, should mark as unresolved', | ||
{ declaration: `const data = {userId: '123'};`, | ||
wireParameters: ['recordId: data.userId'], | ||
expectedStaticParameters: { recordId: { type: 'unresolved', value: 'member_expression' } } }); | ||
wireMetadataParameterTest('when an inline string-literal initialization is used, should use value', | ||
{ wireParameters: ['recordId: "123"'], | ||
expectedStaticParameters: { recordId: { value: '123', type: 'string' } } }); | ||
wireMetadataParameterTest('when an inline numeric-literal initialization is used, should use value', | ||
{ wireParameters: ['size: 100'], | ||
expectedStaticParameters: { size: { value: 100, type: 'number' } } }); | ||
wireMetadataParameterTest('when an inline float-literal initialization is used, should use value', | ||
{ wireParameters: ['underPrice: 50.50'], | ||
expectedStaticParameters: { underPrice: { value: 50.50, type: 'number' } } }); | ||
wireMetadataParameterTest('when an inline boolean-literal initialization is used, should use value', | ||
{ wireParameters: ['isRegistered: true'], | ||
expectedStaticParameters: { isRegistered: { value: true, type: 'boolean' } } }); | ||
wireMetadataParameterTest('when $foo parameters are used, should use name of the parameter', | ||
{ wireParameters: ['recordId: "$userId"'], | ||
expectedVariableParameters: { recordId: 'userId' } }); | ||
wireMetadataParameterTest('when $foo parameters with dots are used, should use name of the parameter', | ||
{ wireParameters: ['recordId: "$userRecord.Id"'], | ||
expectedVariableParameters: { recordId: 'userRecord.Id' } }); | ||
wireMetadataParameterTest('when inline array with a non-string literal is used, should mark as unresolved', | ||
{ declaration: `const bar = '123';`, | ||
wireParameters: ['fields: ["foo", bar]'], | ||
expectedStaticParameters: { fields: {type: 'unresolved', value: 'array_expression'} } }); | ||
wireMetadataParameterTest('when inline array with literals is used, should have the array', | ||
{wireParameters: ['data: ["foo", 123, false]'], | ||
expectedStaticParameters: { data: {type: 'array', value: ['foo', 123, false]} } }); | ||
}); |
@@ -8,5 +8,4 @@ /* | ||
const { generateError, getEngineImportSpecifiers } = require('./utils'); | ||
const { GLOBAL_ATTRIBUTE_MAP, LWC_PACKAGE_EXPORTS, LWC_API_WHITELIST } = require('./constants'); | ||
const { LWC_PACKAGE_EXPORTS, LWC_API_WHITELIST } = require('./constants'); | ||
const { LWCClassErrors } = require('@lwc/errors'); | ||
const CLASS_PROPERTY_OBSERVED_ATTRIBUTES = 'observedAttributes'; | ||
@@ -13,0 +12,0 @@ module.exports = function ({ types: t }) { |
@@ -7,28 +7,3 @@ /* | ||
*/ | ||
function globalAttributeObject(propName) { | ||
return { | ||
propName, | ||
} | ||
} | ||
const GLOBAL_ATTRIBUTE_MAP = new Map([ | ||
['role', globalAttributeObject('role')], | ||
['accesskey', globalAttributeObject('accessKey')], | ||
['class', globalAttributeObject('class')], | ||
['contenteditable', globalAttributeObject('contentEditable')], | ||
['contextmenu', globalAttributeObject('contextmenu')], | ||
['dir', globalAttributeObject('dir')], | ||
['draggable', globalAttributeObject('draggable')], | ||
['dropzone', globalAttributeObject('dropzone')], | ||
['hidden', globalAttributeObject('hidden')], | ||
['id', globalAttributeObject('id')], | ||
['itemprop', globalAttributeObject('itemprop')], | ||
['lang', globalAttributeObject('lang')], | ||
['slot', globalAttributeObject('slot')], | ||
['spellcheck', globalAttributeObject('spellcheck')], | ||
['style', globalAttributeObject('style')], | ||
['tabindex', globalAttributeObject('tabIndex')], | ||
['title', globalAttributeObject('title')], | ||
]); | ||
// This set is for attributes that have a camel cased property name | ||
@@ -103,3 +78,2 @@ // For example, div.tabIndex. | ||
DISALLOWED_PROP_SET, | ||
GLOBAL_ATTRIBUTE_MAP, | ||
LWC_DECORATORS, | ||
@@ -109,5 +83,4 @@ LWC_PACKAGE_ALIAS, | ||
LWC_API_WHITELIST, | ||
LWC_COMPONENT_PROPERTIES, | ||
DECORATOR_TYPES, | ||
}; |
@@ -8,3 +8,3 @@ /* | ||
const { isApiDecorator } = require('./shared'); | ||
const { extractValueMetadata, markAsLWCNode, staticClassProperty } = require('../../utils'); | ||
const { markAsLWCNode, staticClassProperty } = require('../../utils'); | ||
const { LWC_COMPONENT_PROPERTIES: { PUBLIC_PROPS, PUBLIC_METHODS }, DECORATOR_TYPES } = require('../../constants'); | ||
@@ -91,22 +91,2 @@ | ||
} | ||
return publicProps.filter((node) => { | ||
const { type } = node; | ||
return type === 'getter' || type === 'setter' || type === 'property'; | ||
}).map((node) => { | ||
const { path, type } = node; | ||
const parentNode = path.parent; | ||
const parentValue = parentNode && parentNode.value; | ||
const meta = { | ||
type: 'property', | ||
name: path.parentPath.get('key.name').node, | ||
} | ||
if (type === 'property') { | ||
meta.value = extractValueMetadata(parentValue); | ||
} | ||
return meta; | ||
}); | ||
} | ||
@@ -128,7 +108,2 @@ | ||
} | ||
return publicMethods.map(({ path }) => ({ | ||
type: 'method', | ||
name: path.parentPath.get('key.name').node | ||
})); | ||
} | ||
@@ -140,11 +115,5 @@ | ||
const apiProperties = transformPublicProps(t, klassBody, apiDecorators); | ||
const apiMethods = transformPublicMethods(t, klassBody, apiDecorators); | ||
transformPublicProps(t, klassBody, apiDecorators); | ||
transformPublicMethods(t, klassBody, apiDecorators); | ||
if ((apiProperties.length + apiMethods.length) > 0) { | ||
return { | ||
type: 'api', | ||
targets: [...apiProperties, ...apiMethods] | ||
}; | ||
} | ||
} |
@@ -110,13 +110,7 @@ /* | ||
/** Transform the decorators and returns the metadata */ | ||
/** Transform the decorators */ | ||
function transform(t, klass, decorators) { | ||
return DECORATOR_TRANSFORMS.reduce((metadata, { transform }) => { | ||
const decoratorMetadata = transform(t, klass, decorators); | ||
if (decoratorMetadata) { | ||
metadata.push(decoratorMetadata); | ||
} | ||
return metadata; | ||
}, []); | ||
return DECORATOR_TRANSFORMS.forEach(({ transform }) => { | ||
transform(t, klass, decorators); | ||
}); | ||
} | ||
@@ -163,3 +157,2 @@ | ||
const decorators = getLwcDecorators(decoratorImportSpecifiers); | ||
state.file.metadata = Object.assign({}, state.file.metadata, { decorators: [] }); | ||
const grouped = groupDecorator(decorators); | ||
@@ -169,7 +162,3 @@ | ||
validate(klass, decorators); | ||
// 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.decorators.push(...metadata); | ||
transform(t, klass, decorators); | ||
} | ||
@@ -182,3 +171,2 @@ | ||
Class(path, state) { | ||
// don't remove decorators until metadata.js had the chance to visit the Class node | ||
removeDecorators(state.decorators); | ||
@@ -185,0 +173,0 @@ removeImportSpecifiers(state.decoratorImportSpecifiers); |
@@ -53,10 +53,2 @@ /* | ||
); | ||
return { | ||
type: 'track', | ||
targets: trackProperties.map(name => ({ | ||
name, | ||
type: 'property', | ||
})) | ||
}; | ||
} | ||
@@ -63,0 +55,0 @@ } |
@@ -83,3 +83,3 @@ /* | ||
const SUPPORTED_VALUE_TYPE_TO_METADATA_TYPE = { | ||
const SUPPORTED_VALUE_TO_TYPE_MAP = { | ||
StringLiteral: 'string', | ||
@@ -90,61 +90,3 @@ NumericLiteral: 'number', | ||
function getWiredStaticMetadata(properties, referenceLookup) { | ||
const ret = {}; | ||
properties.forEach(s => { | ||
let result = {}; | ||
const valueType = s.value.type; | ||
if (s.key.type === 'Identifier') { | ||
if (valueType === 'ArrayExpression') { | ||
// @wire(getRecord, { fields: ['Id', 'Name'] }) | ||
// @wire(getRecord, { data: [123, false, 'string'] }) | ||
const elements = s.value.elements; | ||
const hasUnsupportedElement = | ||
elements.some(element => !SUPPORTED_VALUE_TYPE_TO_METADATA_TYPE[element.type]); | ||
if (hasUnsupportedElement) { | ||
result = {type: 'unresolved', value: 'array_expression'}; | ||
} else { | ||
result = {type: 'array', value: elements.map(e => e.value)}; | ||
} | ||
} else if (SUPPORTED_VALUE_TYPE_TO_METADATA_TYPE[valueType]) { | ||
// @wire(getRecord, { companyName: ['Acme'] }) | ||
// @wire(getRecord, { size: 100 }) | ||
// @wire(getRecord, { isAdmin: true }) | ||
result = {type: SUPPORTED_VALUE_TYPE_TO_METADATA_TYPE[valueType], value: s.value.value}; | ||
} else if (valueType === 'Identifier') { | ||
// References such as: | ||
// 1. Modules | ||
// import id from '@salesforce/user/id' | ||
// @wire(getRecord, { userId: id }) | ||
// | ||
// 2. 1st order constant references with string literals | ||
// const userId = '123'; | ||
// @wire(getRecord, { userId: userId }) | ||
const reference = referenceLookup(s.value.name); | ||
result = {value: reference.value, type: reference.type}; | ||
if (!result.type) { | ||
result = {type: 'unresolved', value: 'identifier'} | ||
} | ||
} else if (valueType === 'MemberExpression') { | ||
// @wire(getRecord, { userId: recordData.Id }) | ||
result = {type: 'unresolved', value: 'member_expression'}; | ||
} | ||
} | ||
if (!result.type) { | ||
result = {type: 'unresolved'}; | ||
} | ||
ret[s.key.name] = result; | ||
}); | ||
return ret; | ||
} | ||
function getWiredParamMetadata(properties) { | ||
const ret = {}; | ||
properties.forEach(p => { | ||
if (p.key.type === 'Identifier' && p.value.type === 'StringLiteral') { | ||
ret[p.key.name] = p.value.value; | ||
} | ||
}); | ||
return ret; | ||
} | ||
const scopedReferenceLookup = scope => name => { | ||
@@ -168,4 +110,4 @@ const binding = scope.getBinding(name); | ||
const init = binding.path.node.init; | ||
if (init && SUPPORTED_VALUE_TYPE_TO_METADATA_TYPE[init.type]) { | ||
type = SUPPORTED_VALUE_TYPE_TO_METADATA_TYPE[init.type]; | ||
if (init && SUPPORTED_VALUE_TO_TYPE_MAP[init.type]) { | ||
type = SUPPORTED_VALUE_TO_TYPE_MAP[init.type]; | ||
value = init.value; | ||
@@ -182,3 +124,2 @@ } | ||
module.exports = function transform(t, klass, decorators) { | ||
const metadata = []; | ||
const wiredValues = decorators.filter(isWireDecorator).map(({path}) => { | ||
@@ -213,15 +154,2 @@ const [id, config] = path.get('expression.arguments'); | ||
const wireMetadata = { | ||
name: wiredValue.propertyName, | ||
adapter: wiredValue.adapter, | ||
type: isClassMethod ? 'method' : 'property' | ||
}; | ||
if (config) { | ||
wireMetadata.static = getWiredStaticMetadata(wiredValue.static, referenceLookup); | ||
wireMetadata.params = getWiredParamMetadata(wiredValue.params); | ||
} | ||
metadata.push(wireMetadata); | ||
return wiredValue; | ||
@@ -241,9 +169,2 @@ }); | ||
} | ||
if (metadata.length > 0) { | ||
return { | ||
type: 'wire', | ||
targets: metadata | ||
}; | ||
} | ||
}; |
@@ -7,3 +7,2 @@ /* | ||
*/ | ||
const metadata = require('./metadata'); | ||
const component = require('./component'); | ||
@@ -27,3 +26,2 @@ const { decorators } = require('./decorators'); | ||
visitor: mergeVisitors([ | ||
metadata(api), | ||
decorators(api), | ||
@@ -30,0 +28,0 @@ component(api), |
184
src/utils.js
@@ -14,14 +14,2 @@ /* | ||
function findClassMethod(path, name, properties = {}) { | ||
path.assertClassBody(); | ||
return path.get('body').find(path => ( | ||
isClassMethod(path, { | ||
name, | ||
kind: properties.kind || 'method', | ||
static: properties.static | ||
}) | ||
)); | ||
} | ||
function isClassMethod(classMethod, properties = {}) { | ||
@@ -65,59 +53,2 @@ const { kind = 'method', name } = properties; | ||
function getExportedNames(path) { | ||
const programPath = path.isProgram() ? path : path.findParent(node => node.isProgram()); | ||
return exports = programPath.get('body').reduce((names, node) => { | ||
const exportSource = getExportSrc(node && node.node.source); | ||
// export default class App {} | ||
if (node.isExportDefaultDeclaration()) { | ||
names.push(createModuleExportInfo({ type: EXPORT_DEFAULT_DECLARATION, source: exportSource })); | ||
// export * from 'external-module' | ||
} else if (node.isExportDeclaration() && node.type === EXPORT_ALL_DECLARATION) { | ||
names.push(createModuleExportInfo({ type: EXPORT_ALL_DECLARATION, source: exportSource })); | ||
} else if (node.isExportDeclaration() && node.type === EXPORT_NAMED_DECLARATION) { | ||
// export { method } from 'utils' | ||
const specifiers = node.node.specifiers; | ||
if (Array.isArray(specifiers)) { | ||
specifiers.forEach(specifier => { | ||
const exportValue = specifier.exported.name; | ||
names.push(createModuleExportInfo({ | ||
type: EXPORT_NAMED_DECLARATION, | ||
value: exportValue, | ||
source: exportSource | ||
})); | ||
}); | ||
} | ||
const declaration = node.node.declaration; | ||
if (declaration) { | ||
// export const version = 0; | ||
if (declaration.type === 'VariableDeclaration' && Array.isArray(declaration.declarations)) { | ||
declaration.declarations.forEach(nameDeclaration => { | ||
exportValue = nameDeclaration.id.name; | ||
}); | ||
// export class Inner {}; | ||
} else if (declaration.type === 'ClassDeclaration' | ||
|| declaration.type === 'FunctionDeclaration') { | ||
exportValue = declaration.id.name; | ||
} | ||
names.push(createModuleExportInfo({ | ||
type: EXPORT_NAMED_DECLARATION, | ||
value: exportValue, | ||
source: exportSource | ||
})); | ||
} | ||
} | ||
return names; | ||
}, []); | ||
} | ||
function getExportSrc(src) { | ||
@@ -171,18 +102,2 @@ if (!src || !src.value) { | ||
function isComponentClass(classPath, componentBaseClassImports) { | ||
const superClass = classPath.get('superClass'); | ||
return superClass.isIdentifier() && componentBaseClassImports | ||
&& componentBaseClassImports.some(componentBaseClassImport => ( | ||
classPath.scope.bindingIdentifierEquals( | ||
superClass.node.name, | ||
componentBaseClassImport.node | ||
) | ||
)); | ||
} | ||
function isDefaultExport(path) { | ||
return path.parentPath.isExportDefaultDeclaration(); | ||
} | ||
function generateError(source, { errorInfo, messageArgs } = {}) { | ||
@@ -204,100 +119,5 @@ const message = generateErrorMessage(errorInfo, messageArgs); | ||
function extractValueMetadata(valueNode) { | ||
let valueMetadata = { | ||
type: 'unresolved', | ||
value: undefined, | ||
}; | ||
if (!valueNode) { | ||
return valueMetadata; | ||
} | ||
const { type } = valueNode; | ||
if (type === 'StringLiteral') { | ||
valueMetadata = extractStringValueMeta(valueNode); | ||
} else if (type === 'NumericLiteral') { | ||
valueMetadata = extractNumberValueMeta(valueNode); | ||
} else if (type === 'BooleanLiteral') { | ||
valueMetadata = extractBooleanValueMeta(valueNode); | ||
} else if (type === 'NullLiteral') { | ||
valueMetadata = { | ||
type: "null", | ||
value: null, | ||
}; | ||
} else if (type === 'ObjectExpression') { | ||
valueMetadata = extractObjectValueMeta(valueNode); | ||
} else if (type === 'ArrayExpression') { | ||
valueMetadata = extractArrayValueMeta(valueNode); | ||
} | ||
return valueMetadata; | ||
} | ||
function extractStringValueMeta(valueNode) { | ||
return { | ||
type: 'string', | ||
value: valueNode && valueNode.value || undefined, | ||
} | ||
} | ||
function extractNumberValueMeta(valueNode) { | ||
let value = valueNode && valueNode.value; | ||
return { | ||
type: 'number', | ||
value: value === null ? undefined : value | ||
} | ||
} | ||
function extractBooleanValueMeta(valueNode) { | ||
let value = valueNode && valueNode.value; | ||
return { | ||
type: 'boolean', | ||
value: !!(valueNode && valueNode.value), | ||
} | ||
} | ||
function extractArrayValueMeta(valueNode) { | ||
const arrayValueMeta = { | ||
type: 'array', | ||
value: [], | ||
} | ||
if (!valueNode) { | ||
return arrayValueMeta; | ||
} | ||
return { | ||
type: 'array', | ||
value: valueNode.elements.map((elem) => extractValueMetadata(elem)), | ||
} | ||
} | ||
function extractObjectValueMeta(valueNode) { | ||
const objectValueMeta = { | ||
type: 'object', | ||
value: {}, | ||
} | ||
if (!valueNode) { | ||
return objectValueMeta; | ||
} | ||
const values = {}; | ||
valueNode.properties.forEach(({key, value}) => { | ||
values[key.name] = extractValueMetadata(value); | ||
}); | ||
return { | ||
type: 'object', | ||
value: values, | ||
} | ||
} | ||
module.exports = { | ||
isLWCNode, | ||
markAsLWCNode, | ||
findClassMethod, | ||
isClassMethod, | ||
@@ -309,6 +129,2 @@ isGetterClassMethod, | ||
generateError, | ||
isComponentClass, | ||
isDefaultExport, | ||
getExportedNames, | ||
extractValueMetadata, | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
96935
29
2726
+ Added@lwc/errors@0.35.6-alpha1(transitive)
- Removed@lwc/errors@0.35.5(transitive)
Updated@lwc/errors@0.35.6-alpha1