UNPKG

chrome-devtools-frontend

Version:
87 lines (78 loc) 2.55 kB
// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; const {isLitHtmlRenderCall} = require('./utils.js'); module.exports = { meta: { type: 'problem', docs: { description: 'enforce use of {host: this} when rendering LitHtml', category: 'Possible Errors', }, fixable: 'code', messages: { missingHostOption: 'LitHtml.render call does not include {host: this} as the third option. This may cause event handlers to be called with the wrong scope.', invalidHostOption: 'The host option must be set to `this` to ensure event listeners are bound correctly.' }, schema: [] // no options }, create: function(context) { return { CallExpression(node) { if (!isLitHtmlRenderCall(node)) { return; } const argumentsToRenderCall = node.arguments; if (!argumentsToRenderCall) { // Invalid, but TypeScript will catch it. // So no need to do anything. return; } const optionsArgument = argumentsToRenderCall[2]; if (!optionsArgument) { context.report({ node, messageId: 'missingHostOption', fix(fixer) { if (argumentsToRenderCall[1]) { return [fixer.insertTextAfter(argumentsToRenderCall[1], ', {host: this}')]; } return []; } }); return; } if (optionsArgument.type !== 'ObjectExpression') { // Invalid, but TypeScript will catch it. return; } let hostProperty = null; for (const property of optionsArgument.properties) { if (property.key.name === 'host') { hostProperty = property; break; } } if (!hostProperty) { context.report({ node: optionsArgument, messageId: 'missingHostOption', fix(fixer) { const lastProperty = optionsArgument.properties[optionsArgument.properties.length - 1]; return [ fixer.insertTextAfter(lastProperty, ', host: this'), ]; } }); return; } if (hostProperty.value.type !== 'ThisExpression') { context.report({node: hostProperty, messageId: 'invalidHostOption'}); return; } }, }; } };