ember-codemods / ember-no-implicit-this-codemod Goto Github PK
View Code? Open in Web Editor NEWTemplate codemod for refactoring from `{{foo}}` to `{{this.foo}}`
License: MIT License
Template codemod for refactoring from `{{foo}}` to `{{this.foo}}`
License: MIT License
For an app that has multiple apps co-located or if there are components invoked from addons that reside outside of the project, the component gets prefixed with this
when running the codemod.
In multiple places in my codebase, sometimes properties are not prefixed:
{{report.title}}
remains unchanged, for example. In the same file {{report.data}}
was transformed to {{this.report.data}}
I'm not sure what is causing this. It passes in Travis but fails on AppVeyor. It's running npx ember-no-implicit-this-codemod http://localhost:4200/ app/
on CI.
RangeError: Maximum call stack size exceeded
at normalizeStringWin32 (path.js:33:30)
at Object.resolve (path.js:328:20)
at sync (C:\Users\appveyor\AppData\Roaming\npm-cache\_npx\1512\node_modules\ember-no-implicit-this-codemod\node_modules\mkdirp\index.js:68:14)
https://ci.appveyor.com/project/embercli/ember-cli-update/builds/26931625#L4337
I have several template-only components in one of my apps, and when running this codemod they are not changed at all. I would have expected all non-helper/non-component/non-modifier curlies to be prefixed with @
.
data-test-
attributes are prefixed with this
for curly bracket invoked components. Example diff:
-{{#paper-card data-test-job-profile-status as |card|}}
+{{#paper-card this.data-test-job-profile-status as |card|}}
The same attributes are handled properly for angle bracket invoked components.
I suppose I could run https://github.com/ember-codemods/ember-angle-brackets-codemod first. If that is the expectation then perhaps adding a note to the readme would be called for.
/Users/owenschleicher/.npm/_npx/d0f35745626ae5ac/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:217
throw new Error('Evaluation failed: ' + helper_js_1.helper.getExceptionMessage(exceptionDetails));
^
Error: Evaluation failed: TypeError: Cannot convert undefined or null to object
at Function.keys (<anonymous>)
at __puppeteer_evaluation_script__:9:30
at ExecutionContext._evaluateInternal (/Users/owenschleicher/.npm/_npx/d0f35745626ae5ac/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:217:19)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async ExecutionContext.evaluate (/Users/owenschleicher/.npm/_npx/d0f35745626ae5ac/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:106:16)
at async gatherTelemetry (/Users/owenschleicher/.npm/_npx/d0f35745626ae5ac/node_modules/ember-codemods-telemetry-helpers/lib/gather/gather-telemetry.js:29:21)
at async /Users/owenschleicher/.npm/_npx/d0f35745626ae5ac/node_modules/ember-no-implicit-this-codemod/bin/cli.js:15:3
Node.js v18.2.0
Before:
After:
Current github master (3df3c19) + current master of telemetry-helpers (as the currently released version breaks on Windows)
ember serve
in ember-quickstart-codemod
node ./bin/telemetry.js http://localhost:4200
, observe successful outputnode ./bin/cli.js no-implicit-this ~/ember-quickstart/app/
. Observe that no templates are modified.Output from ember version --verbose && npm --version && yarn --version
:
ember-cli: 3.11.0-beta.3
http_parser: 2.8.0
node: 10.16.0
v8: 6.8.275.32-node.52
uv: 1.28.0
zlib: 1.2.11
brotli: 1.0.7
ares: 1.15.0
modules: 64
nghttp2: 1.34.0
napi: 4
openssl: 1.1.1b
icu: 64.2
unicode: 12.1
cldr: 35.1
tz: 2019a
os: linux x64
6.9.0
1.17.3
Telemetry output:
{ '@ember-data/adapter/adapter':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'defaultSerializer',
'findRecord',
'findAll',
'query',
'queryRecord',
'generateIdForRecord',
'serialize',
'createRecord',
'updateRecord',
'deleteRecord',
'coalesceFindRequests',
'findMany',
'groupRecordsForFindMany',
'shouldReloadRecord',
'shouldReloadAll',
'shouldBackgroundReloadRecord',
'shouldBackgroundReloadAll' ],
type: 'EmberObject' },
'@ember-data/adapter/index':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'defaultSerializer',
'findRecord',
'findAll',
'query',
'queryRecord',
'generateIdForRecord',
'serialize',
'createRecord',
'updateRecord',
'deleteRecord',
'coalesceFindRequests',
'findMany',
'groupRecordsForFindMany',
'shouldReloadRecord',
'shouldReloadAll',
'shouldBackgroundReloadRecord',
'shouldBackgroundReloadAll' ],
type: 'EmberObject' },
'@ember-data/adapter/json-api':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'defaultSerializer',
'ajaxOptions',
'coalesceFindRequests',
'findMany',
'pathForType',
'updateRecord' ],
type: 'EmberObject' },
'@ember-data/adapter/rest':
{ computedProperties: [ 'fastboot', 'useFetch' ],
ownActions: [],
ownProperties:
[ 'buildURL',
'_buildURL',
'urlForFindRecord',
'urlForFindAll',
'urlForQuery',
'urlForQueryRecord',
'urlForFindMany',
'urlForFindHasMany',
'urlForFindBelongsTo',
'urlForCreateRecord',
'urlForUpdateRecord',
'urlForDeleteRecord',
'urlPrefix',
'pathForType',
'defaultSerializer',
'fastboot',
'useFetch',
'sortQueryParams',
'coalesceFindRequests',
'findRecord',
'findAll',
'query',
'queryRecord',
'findMany',
'findHasMany',
'findBelongsTo',
'createRecord',
'updateRecord',
'deleteRecord',
'_stripIDFromURL',
'maxURLLength',
'groupRecordsForFindMany',
'handleResponse',
'isSuccess',
'isInvalid',
'ajax',
'_ajaxRequest',
'_najaxRequest',
'_fetchRequest',
'_ajax',
'ajaxOptions',
'_ajaxURL',
'parseErrorResponse',
'normalizeErrorResponse',
'generatedDetailedMessage',
'buildQuery' ],
type: 'EmberObject' },
'@ember-data/model/index':
{ computedProperties:
[ 'isEmpty',
'isLoading',
'isLoaded',
'hasDirtyAttributes',
'isSaving',
'isDeleted',
'isNew',
'isValid',
'dirtyType',
'errors' ],
ownActions: [],
ownProperties:
[ 'on',
'one',
'trigger',
'off',
'has',
'isEmpty',
'isLoading',
'isLoaded',
'hasDirtyAttributes',
'isSaving',
'isDeleted',
'isNew',
'isValid',
'dirtyType',
'isError',
'isReloading',
'currentState',
'_internalModel',
'store',
'errors',
'adapterError',
'serialize',
'toJSON',
'ready',
'didLoad',
'didUpdate',
'didCreate',
'didDelete',
'becameInvalid',
'becameError',
'rolledBack',
'send',
'transitionTo',
'deleteRecord',
'destroyRecord',
'unloadRecord',
'_notifyProperties',
'changedAttributes',
'rollbackAttributes',
'_createSnapshot',
'toStringExtension',
'save',
'reload',
'attr',
'belongsTo',
'hasMany',
'_debugInfo',
'notifyBelongsToChange',
'eachRelationship',
'relationshipFor',
'inverseFor',
'notifyHasManyAdded',
'eachAttribute',
'init' ],
type: 'EmberObject' },
'@ember-data/serializer/index':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'normalizeResponse', 'serialize', 'normalize' ],
type: 'EmberObject' },
'@ember-data/serializer/json-api':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ '_normalizeDocumentHelper',
'_normalizeRelationshipDataHelper',
'_normalizeResourceHelper',
'pushPayload',
'_normalizeResponse',
'normalizeQueryRecordResponse',
'extractAttributes',
'extractRelationship',
'extractRelationships',
'_extractType',
'modelNameFromPayloadKey',
'payloadKeyFromModelName',
'normalize',
'keyForAttribute',
'keyForRelationship',
'serialize',
'serializeAttribute',
'serializeBelongsTo',
'serializeHasMany',
'willMergeMixin',
'warnMessageForUndefinedType',
'warnMessageNoModelForType' ],
type: 'EmberObject' },
'@ember-data/serializer/json':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'primaryKey',
'mergedProperties',
'applyTransforms',
'normalizeResponse',
'normalizeFindRecordResponse',
'normalizeQueryRecordResponse',
'normalizeFindAllResponse',
'normalizeFindBelongsToResponse',
'normalizeFindHasManyResponse',
'normalizeFindManyResponse',
'normalizeQueryResponse',
'normalizeCreateRecordResponse',
'normalizeDeleteRecordResponse',
'normalizeUpdateRecordResponse',
'normalizeSaveResponse',
'normalizeSingleResponse',
'normalizeArrayResponse',
'_normalizeResponse',
'normalize',
'extractId',
'extractAttributes',
'extractRelationship',
'extractPolymorphicRelationship',
'extractRelationships',
'modelNameFromPayloadKey',
'normalizeRelationships',
'normalizeUsingDeclaredMapping',
'_getMappedKey',
'_canSerialize',
'_mustSerialize',
'shouldSerializeHasMany',
'serialize',
'serializeIntoHash',
'serializeAttribute',
'serializeBelongsTo',
'serializeHasMany',
'serializePolymorphicType',
'extractMeta',
'extractErrors',
'keyForAttribute',
'keyForRelationship',
'keyForLink',
'transformFor' ],
type: 'EmberObject' },
'@ember-data/serializer/rest':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'keyForPolymorphicType',
'_normalizeArray',
'_normalizePolymorphicRecord',
'_normalizeResponse',
'isPrimaryType',
'pushPayload',
'modelNameFromPayloadKey',
'serialize',
'serializeIntoHash',
'payloadKeyFromModelName',
'serializePolymorphicType',
'extractPolymorphicRelationship',
'warnMessageNoModelForKey' ],
type: 'EmberObject' },
'@ember-data/serializer/serializer':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'normalizeResponse', 'serialize', 'normalize' ],
type: 'EmberObject' },
'@ember-data/serializer/transform':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'serialize', 'deserialize' ],
type: 'EmberObject' },
'@ember-data/serializer/transforms/boolean':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'deserialize', 'serialize' ],
type: 'EmberObject' },
'@ember-data/serializer/transforms/date':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'deserialize', 'serialize' ],
type: 'EmberObject' },
'@ember-data/serializer/transforms/number':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'deserialize', 'serialize' ],
type: 'EmberObject' },
'@ember-data/serializer/transforms/string':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'deserialize', 'serialize' ],
type: 'EmberObject' },
'@ember-data/serializer/transforms/transform':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'serialize', 'deserialize' ],
type: 'EmberObject' },
'@ember-data/store/index':
{ computedProperties: [ 'defaultAdapter' ],
ownActions: [],
ownProperties:
[ 'init',
'adapter',
'defaultAdapter',
'createRecord',
'_generateId',
'deleteRecord',
'unloadRecord',
'find',
'findRecord',
'_findRecord',
'_findByInternalModel',
'_findEmptyInternalModel',
'findByIds',
'_fetchRecord',
'_scheduleFetchMany',
'_scheduleFetch',
'flushAllPendingFetches',
'_flushPendingFetchForType',
'getReference',
'peekRecord',
'_reloadRecord',
'hasRecordForId',
'recordForId',
'_getInternalModelForId',
'_internalModelForId',
'findMany',
'findHasMany',
'_findHasManyByJsonApiResource',
'_getHasManyByJsonApiResource',
'findBelongsTo',
'_fetchBelongsToLinkFromResource',
'_findBelongsToByJsonApiResource',
'query',
'_query',
'queryRecord',
'findAll',
'_fetchAll',
'_didUpdateAll',
'peekAll',
'unloadAll',
'filter',
'scheduleSave',
'flushPendingSave',
'didSaveRecord',
'recordWasInvalid',
'recordWasError',
'setRecordId',
'_setRecordId',
'_internalModelsFor',
'_newlyCreatedModelsFor',
'_load',
'modelFor',
'_modelFactoryFor',
'_hasModelFor',
'push',
'_push',
'_pushInternalModel',
'pushPayload',
'reloadManyArray',
'reloadBelongsTo',
'_relationshipMetaFor',
'_attributesDefinitionFor',
'_relationshipsDefinitionFor',
'_internalModelForResource',
'_createRecordData',
'createRecordDataFor',
'recordDataFor',
'_internalModelForRecordData',
'normalize',
'newClientId',
'_buildInternalModel',
'_existingInternalModelForId',
'recordWasLoaded',
'_removeFromIdMap',
'adapterFor',
'serializerFor',
'willDestroy',
'_updateRelationshipState',
'_flushUpdatedRelationships',
'_updateInternalModel',
'_flushUpdatedInternalModels',
'_pushResourceIdentifier',
'_pushResourceIdentifiers' ],
type: 'Service' },
'ember-ajax/ajax-request':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'contentType',
'request',
'raw',
'_makeRequest',
'post',
'put',
'patch',
'del',
'delete',
'get',
'_addTypeToOptionsFor',
'_getFullHeadersHash',
'options',
'_buildURL',
'handleResponse',
'_createCorrectError',
'_matchHosts',
'_shouldSendHeaders',
'generateDetailedMessage',
'isUnauthorizedError',
'isForbiddenError',
'isInvalidError',
'isBadRequestError',
'isNotFoundError',
'isGoneError',
'isAbortError',
'isConflictError',
'isServerError',
'isSuccess',
'parseErrorResponse',
'normalizeErrorResponse' ],
type: 'EmberObject' },
'ember-ajax/services/ajax':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'contentType',
'request',
'raw',
'_makeRequest',
'post',
'put',
'patch',
'del',
'delete',
'get',
'_addTypeToOptionsFor',
'_getFullHeadersHash',
'options',
'_buildURL',
'handleResponse',
'_createCorrectError',
'_matchHosts',
'_shouldSendHeaders',
'generateDetailedMessage',
'isUnauthorizedError',
'isForbiddenError',
'isInvalidError',
'isBadRequestError',
'isNotFoundError',
'isGoneError',
'isAbortError',
'isConflictError',
'isServerError',
'isSuccess',
'parseErrorResponse',
'normalizeErrorResponse' ],
type: 'Service' },
'ember-data/adapter':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'defaultSerializer',
'findRecord',
'findAll',
'query',
'queryRecord',
'generateIdForRecord',
'serialize',
'createRecord',
'updateRecord',
'deleteRecord',
'coalesceFindRequests',
'findMany',
'groupRecordsForFindMany',
'shouldReloadRecord',
'shouldReloadAll',
'shouldBackgroundReloadRecord',
'shouldBackgroundReloadAll' ],
type: 'EmberObject' },
'ember-data/adapters/json-api':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'defaultSerializer',
'ajaxOptions',
'coalesceFindRequests',
'findMany',
'pathForType',
'updateRecord' ],
type: 'EmberObject' },
'ember-data/adapters/rest':
{ computedProperties: [ 'fastboot', 'useFetch' ],
ownActions: [],
ownProperties:
[ 'buildURL',
'_buildURL',
'urlForFindRecord',
'urlForFindAll',
'urlForQuery',
'urlForQueryRecord',
'urlForFindMany',
'urlForFindHasMany',
'urlForFindBelongsTo',
'urlForCreateRecord',
'urlForUpdateRecord',
'urlForDeleteRecord',
'urlPrefix',
'pathForType',
'defaultSerializer',
'fastboot',
'useFetch',
'sortQueryParams',
'coalesceFindRequests',
'findRecord',
'findAll',
'query',
'queryRecord',
'findMany',
'findHasMany',
'findBelongsTo',
'createRecord',
'updateRecord',
'deleteRecord',
'_stripIDFromURL',
'maxURLLength',
'groupRecordsForFindMany',
'handleResponse',
'isSuccess',
'isInvalid',
'ajax',
'_ajaxRequest',
'_najaxRequest',
'_fetchRequest',
'_ajax',
'ajaxOptions',
'_ajaxURL',
'parseErrorResponse',
'normalizeErrorResponse',
'generatedDetailedMessage',
'buildQuery' ],
type: 'EmberObject' },
'ember-data/model':
{ computedProperties:
[ 'isEmpty',
'isLoading',
'isLoaded',
'hasDirtyAttributes',
'isSaving',
'isDeleted',
'isNew',
'isValid',
'dirtyType',
'errors' ],
ownActions: [],
ownProperties:
[ 'on',
'one',
'trigger',
'off',
'has',
'isEmpty',
'isLoading',
'isLoaded',
'hasDirtyAttributes',
'isSaving',
'isDeleted',
'isNew',
'isValid',
'dirtyType',
'isError',
'isReloading',
'currentState',
'_internalModel',
'store',
'errors',
'adapterError',
'serialize',
'toJSON',
'ready',
'didLoad',
'didUpdate',
'didCreate',
'didDelete',
'becameInvalid',
'becameError',
'rolledBack',
'send',
'transitionTo',
'deleteRecord',
'destroyRecord',
'unloadRecord',
'_notifyProperties',
'changedAttributes',
'rollbackAttributes',
'_createSnapshot',
'toStringExtension',
'save',
'reload',
'attr',
'belongsTo',
'hasMany',
'_debugInfo',
'notifyBelongsToChange',
'eachRelationship',
'relationshipFor',
'inverseFor',
'notifyHasManyAdded',
'eachAttribute',
'init' ],
type: 'EmberObject' },
'ember-data/serializer':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'normalizeResponse', 'serialize', 'normalize' ],
type: 'EmberObject' },
'ember-data/serializers/json-api':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ '_normalizeDocumentHelper',
'_normalizeRelationshipDataHelper',
'_normalizeResourceHelper',
'pushPayload',
'_normalizeResponse',
'normalizeQueryRecordResponse',
'extractAttributes',
'extractRelationship',
'extractRelationships',
'_extractType',
'modelNameFromPayloadKey',
'payloadKeyFromModelName',
'normalize',
'keyForAttribute',
'keyForRelationship',
'serialize',
'serializeAttribute',
'serializeBelongsTo',
'serializeHasMany',
'willMergeMixin',
'warnMessageForUndefinedType',
'warnMessageNoModelForType' ],
type: 'EmberObject' },
'ember-data/serializers/json':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'primaryKey',
'mergedProperties',
'applyTransforms',
'normalizeResponse',
'normalizeFindRecordResponse',
'normalizeQueryRecordResponse',
'normalizeFindAllResponse',
'normalizeFindBelongsToResponse',
'normalizeFindHasManyResponse',
'normalizeFindManyResponse',
'normalizeQueryResponse',
'normalizeCreateRecordResponse',
'normalizeDeleteRecordResponse',
'normalizeUpdateRecordResponse',
'normalizeSaveResponse',
'normalizeSingleResponse',
'normalizeArrayResponse',
'_normalizeResponse',
'normalize',
'extractId',
'extractAttributes',
'extractRelationship',
'extractPolymorphicRelationship',
'extractRelationships',
'modelNameFromPayloadKey',
'normalizeRelationships',
'normalizeUsingDeclaredMapping',
'_getMappedKey',
'_canSerialize',
'_mustSerialize',
'shouldSerializeHasMany',
'serialize',
'serializeIntoHash',
'serializeAttribute',
'serializeBelongsTo',
'serializeHasMany',
'serializePolymorphicType',
'extractMeta',
'extractErrors',
'keyForAttribute',
'keyForRelationship',
'keyForLink',
'transformFor' ],
type: 'EmberObject' },
'ember-data/serializers/rest':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'keyForPolymorphicType',
'_normalizeArray',
'_normalizePolymorphicRecord',
'_normalizeResponse',
'isPrimaryType',
'pushPayload',
'modelNameFromPayloadKey',
'serialize',
'serializeIntoHash',
'payloadKeyFromModelName',
'serializePolymorphicType',
'extractPolymorphicRelationship',
'warnMessageNoModelForKey' ],
type: 'EmberObject' },
'ember-data/store':
{ computedProperties: [ 'defaultAdapter' ],
ownActions: [],
ownProperties:
[ 'init',
'adapter',
'defaultAdapter',
'createRecord',
'_generateId',
'deleteRecord',
'unloadRecord',
'find',
'findRecord',
'_findRecord',
'_findByInternalModel',
'_findEmptyInternalModel',
'findByIds',
'_fetchRecord',
'_scheduleFetchMany',
'_scheduleFetch',
'flushAllPendingFetches',
'_flushPendingFetchForType',
'getReference',
'peekRecord',
'_reloadRecord',
'hasRecordForId',
'recordForId',
'_getInternalModelForId',
'_internalModelForId',
'findMany',
'findHasMany',
'_findHasManyByJsonApiResource',
'_getHasManyByJsonApiResource',
'findBelongsTo',
'_fetchBelongsToLinkFromResource',
'_findBelongsToByJsonApiResource',
'query',
'_query',
'queryRecord',
'findAll',
'_fetchAll',
'_didUpdateAll',
'peekAll',
'unloadAll',
'filter',
'scheduleSave',
'flushPendingSave',
'didSaveRecord',
'recordWasInvalid',
'recordWasError',
'setRecordId',
'_setRecordId',
'_internalModelsFor',
'_newlyCreatedModelsFor',
'_load',
'modelFor',
'_modelFactoryFor',
'_hasModelFor',
'push',
'_push',
'_pushInternalModel',
'pushPayload',
'reloadManyArray',
'reloadBelongsTo',
'_relationshipMetaFor',
'_attributesDefinitionFor',
'_relationshipsDefinitionFor',
'_internalModelForResource',
'_createRecordData',
'createRecordDataFor',
'recordDataFor',
'_internalModelForRecordData',
'normalize',
'newClientId',
'_buildInternalModel',
'_existingInternalModelForId',
'recordWasLoaded',
'_removeFromIdMap',
'adapterFor',
'serializerFor',
'willDestroy',
'_updateRelationshipState',
'_flushUpdatedRelationships',
'_updateInternalModel',
'_flushUpdatedInternalModels',
'_pushResourceIdentifier',
'_pushResourceIdentifiers' ],
type: 'Service' },
'ember-data/transform':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'serialize', 'deserialize' ],
type: 'EmberObject' },
'ember-resolver/index':
{ computedProperties: [ 'moduleNameLookupPatterns' ],
ownActions: [],
ownProperties:
[ 'resolveOther',
'parseName',
'pluralizedTypes',
'moduleRegistry',
'makeToString',
'shouldWrapInClassFactory',
'init',
'normalize',
'resolve',
'_normalize',
'pluralize',
'podBasedLookupWithPrefix',
'podBasedModuleName',
'podBasedComponentsInSubdir',
'resolveEngine',
'resolveRouteMap',
'resolveTemplate',
'mainModuleName',
'defaultModuleName',
'prefix',
'moduleNameLookupPatterns',
'findModuleName',
'chooseModuleName',
'lookupDescription',
'_logLookup',
'knownForType',
'translateToContainerFullname',
'_extractDefaultExport' ],
type: 'EmberObject' },
'ember-resolver/resolver':
{ computedProperties: [ 'moduleNameLookupPatterns' ],
ownActions: [],
ownProperties:
[ 'resolveOther',
'parseName',
'pluralizedTypes',
'moduleRegistry',
'makeToString',
'shouldWrapInClassFactory',
'init',
'normalize',
'resolve',
'_normalize',
'pluralize',
'podBasedLookupWithPrefix',
'podBasedModuleName',
'podBasedComponentsInSubdir',
'resolveEngine',
'resolveRouteMap',
'resolveTemplate',
'mainModuleName',
'defaultModuleName',
'prefix',
'moduleNameLookupPatterns',
'findModuleName',
'chooseModuleName',
'lookupDescription',
'_logLookup',
'knownForType',
'translateToContainerFullname',
'_extractDefaultExport' ],
type: 'EmberObject' },
'ember-resolver/resolvers/classic/container-debug-adapter':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ '_moduleRegistry',
'init',
'canCatalogEntriesByType',
'catalogEntriesByType' ],
type: 'EmberObject' },
'ember-resolver/resolvers/classic/index':
{ computedProperties: [ 'moduleNameLookupPatterns' ],
ownActions: [],
ownProperties:
[ 'resolveOther',
'parseName',
'pluralizedTypes',
'moduleRegistry',
'makeToString',
'shouldWrapInClassFactory',
'init',
'normalize',
'resolve',
'_normalize',
'pluralize',
'podBasedLookupWithPrefix',
'podBasedModuleName',
'podBasedComponentsInSubdir',
'resolveEngine',
'resolveRouteMap',
'resolveTemplate',
'mainModuleName',
'defaultModuleName',
'prefix',
'moduleNameLookupPatterns',
'findModuleName',
'chooseModuleName',
'lookupDescription',
'_logLookup',
'knownForType',
'translateToContainerFullname',
'_extractDefaultExport' ],
type: 'EmberObject' },
'ember-welcome-page/components/welcome-page':
{ computedProperties: [ 'emberVersion', 'canAngleBracket', 'isModuleUnification' ],
ownActions: [],
ownProperties:
[ 'layout',
'emberVersion',
'canAngleBracket',
'isModuleUnification' ],
type: 'Component' },
'ember-quickstart/app':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'modulePrefix', 'Resolver' ],
type: 'Application' },
'ember-quickstart/components/old-school':
{ computedProperties: [],
ownActions: [],
ownProperties: [],
type: 'Component' },
'ember-quickstart/components/welcome-page':
{ computedProperties: [ 'emberVersion', 'canAngleBracket', 'isModuleUnification' ],
ownActions: [],
ownProperties:
[ 'layout',
'emberVersion',
'canAngleBracket',
'isModuleUnification' ],
type: 'Component' },
'ember-quickstart/resolver':
{ computedProperties: [ 'moduleNameLookupPatterns' ],
ownActions: [],
ownProperties:
[ 'resolveOther',
'parseName',
'pluralizedTypes',
'moduleRegistry',
'makeToString',
'shouldWrapInClassFactory',
'init',
'normalize',
'resolve',
'_normalize',
'pluralize',
'podBasedLookupWithPrefix',
'podBasedModuleName',
'podBasedComponentsInSubdir',
'resolveEngine',
'resolveRouteMap',
'resolveTemplate',
'mainModuleName',
'defaultModuleName',
'prefix',
'moduleNameLookupPatterns',
'findModuleName',
'chooseModuleName',
'lookupDescription',
'_logLookup',
'knownForType',
'translateToContainerFullname',
'_extractDefaultExport' ],
type: 'EmberObject' },
'ember-quickstart/router':
{ computedProperties: [],
ownActions: [],
ownProperties: [ 'location', 'rootURL' ],
type: 'Router' },
'ember-quickstart/services/ajax':
{ computedProperties: [],
ownActions: [],
ownProperties:
[ 'contentType',
'request',
'raw',
'_makeRequest',
'post',
'put',
'patch',
'del',
'delete',
'get',
'_addTypeToOptionsFor',
'_getFullHeadersHash',
'options',
'_buildURL',
'handleResponse',
'_createCorrectError',
'_matchHosts',
'_shouldSendHeaders',
'generateDetailedMessage',
'isUnauthorizedError',
'isForbiddenError',
'isInvalidError',
'isBadRequestError',
'isNotFoundError',
'isGoneError',
'isAbortError',
'isConflictError',
'isServerError',
'isSuccess',
'parseErrorResponse',
'normalizeErrorResponse' ],
type: 'Service' } }
If I run npx ember-no-implicit-this-codemod http://localhost:4200 /dev/ember-cli-blog/app/**/*.hbs
it keeps downloading chromium and other npm modules and gives me this error:
C:\dev\ember-no-implicit-this-codemod>npx ember-no-implicit-this-codemod http://localhost:4200 /dev/ember-cli-blog/app/**/*.hbs
Downloading Chromium r686378 - 143 Mb [====================] 100% 0.0s
(node:9532) UnhandledPromiseRejectionWarning: Error: EEXIST: file already exists, mkdir 'C:\Users\Martin\AppData\Local\Temp\Martin\if-you-need-to-delete-this-open-an-issue-sync-disk-cache'
at Object.mkdirSync (fs.js:757:3)
at sync (C:\Users\Martin\AppData\Roaming\npm-cache\_npx\9532\node_modules\ember-no-implicit-this-codemod\node_modules\mkdirp\index.js:71:13)
at sync (C:\Users\Martin\AppData\Roaming\npm-cache\_npx\9532\node_modules\ember-no-implicit-this-codemod\node_modules\mkdirp\index.js:77:24)
at sync (C:\Users\Martin\AppData\Roaming\npm-cache\_npx\9532\node_modules\ember-no-implicit-this-codemod\node_modules\mkdirp\index.js:78:17)
at sync (C:\Users\Martin\AppData\Roaming\npm-cache\_npx\9532\node_modules\ember-no-implicit-this-codemod\node_modules\mkdirp\index.js:78:17)
at sync (C:\Users\Martin\AppData\Roaming\npm-cache\_npx\9532\node_modules\ember-no-implicit-this-codemod\node_modules\mkdirp\index.js:78:17)
at sync (C:\Users\Martin\AppData\Roaming\npm-cache\_npx\9532\node_modules\ember-no-implicit-this-codemod\node_modules\mkdirp\index.js:78:17)
at sync (C:\Users\Martin\AppData\Roaming\npm-cache\_npx\9532\node_modules\ember-no-implicit-this-codemod\node_modules\mkdirp\index.js:78:17)
at sync (C:\Users\Martin\AppData\Roaming\npm-cache\_npx\9532\node_modules\ember-no-implicit-this-codemod\node_modules\mkdirp\index.js:78:17)
at sync (C:\Users\Martin\AppData\Roaming\npm-cache\_npx\9532\node_modules\ember-no-implicit-this-codemod\node_modules\mkdirp\index.js:78:17)
(node:9532) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:9532) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
It seems related to this test error:
C:\dev\ember-no-implicit-this-codemod>npm test
> [email protected] test C:\dev\ember-no-implicit-this-codemod
> jest
jest-haste-map: Haste module naming collision: app
The following files share their name; please adjust your hasteImpl:
* <rootDir>\test\fixtures\3.10\input\package.json
* <rootDir>\test\fixtures\3.10\output\package.json
FAIL transforms/no-implicit-this/test.js
โ Test suite failed to run
RangeError: Maximum call stack size exceeded
at sync (node_modules/mkdirp/index.js:92:27)
at sync (node_modules/mkdirp/index.js:77:24)
at sync (node_modules/mkdirp/index.js:78:17)
at sync (node_modules/mkdirp/index.js:78:17)
at sync (node_modules/mkdirp/index.js:78:17)
at sync (node_modules/mkdirp/index.js:78:17)
at sync (node_modules/mkdirp/index.js:78:17)
at sync (node_modules/mkdirp/index.js:78:17)
at sync (node_modules/mkdirp/index.js:78:17)
at sync (node_modules/mkdirp/index.js:78:17)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 5.231s
Ran all test suites.
npm ERR! Test failed. See above for more details.
C:\dev\ember-no-implicit-this-codemod>
Take the following app structure:
app/
routes/
-- application.js
templates/
-- application.hbs
The route returns a model
of some sort and the template accesses {{model}}
. There is no specific controller for the template.
Because the telemetry doesn't pick up that there is an associated controller for application.hbs it doesn't modify the file.
Is there a special mode we could add, --route-template=true
?, which won't require the template to have a backing file to have it modified? This would allow us to modify {{model}}
to be {{this.model}}
(or {{@model}}
from 3.14)
This won't just affect the model
property but also others where we may use the controller.set('someProperty', 'blah')
pattern in the route's afterModel
hook.
{{#if @foo}}
became {{#if this.foo}}
Hi there! I discovered this while trying to run on my M1 Pro Mac. Trying to run against a 3.28 app, but I believe this is due to an old telemetry package.
$ npx ember-no-implicit-this-codemod http://localhost:4200 app/**/*.hbs
The chromium binary is not available for arm64:
If you are on Ubuntu, you can install with:
apt-get install chromium-browser
/Users/dean/.npm/_npx/92999/lib/node_modules/ember-no-implicit-this-codemod/node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserFetcher.js:112
throw new Error();
^
Error
at /Users/dean/.npm/_npx/92999/lib/node_modules/ember-no-implicit-this-codemod/node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserFetcher.js:112:19
at FSReqCallback.oncomplete (fs.js:192:21)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] install: `node install.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
hasBlock
seems to be a special kind of thing that should not be prefixed with this.
or @
.
see https://api.emberjs.com/ember/3.14/classes/Ember.Templates.helpers/methods/hasBlock?anchor=hasBlock
Before
After
Expected
I'm not sure what happened here, but it seems that the text
curlies were not converted properly
Before:
After:
Current github master (3df3c19) + current master of telemetry-helpers (as the currently released version breaks on Windows)
In current Ember apps components and helpers have priority over properties with the same name.
In other words: if a controller has a property foo
, there is a component named foo
, and the controller template renders {{foo}}
then the component will be used instead of the property.
This codemod seems to assume the opposite though and gives properties priority over components and helpers.
Steps to repro:
C:\code\ember-no-implicit-this-codemod>ember version --verbose && npm --version && yarn --version
ember-cli: 3.11.0-beta.3
http_parser: 2.8.0
node: 10.16.0
v8: 6.8.275.32-node.52
uv: 1.28.0
zlib: 1.2.11
brotli: 1.0.7
ares: 1.15.0
modules: 64
nghttp2: 1.34.0
napi: 4
openssl: 1.1.1b
icu: 64.2
unicode: 12.1
cldr: 35.1
tz: 2019a
os: win32 x64
6.9.0
1.15.2
Is it possible for this codemod to support pods layout?
This codemod currently uses analyzeEmberObject
exported from ember-codemods-telemetry-helpers
. It turns out that the analyzeEmberObject
implementation is very specific to the native class codemod that it was extracted from, and thus it only recognizes EmberObject
and its descendants when determining the type
property:
To fix this, we should replace analyzeEmberObject
with our own implementation.
This is probably the root cause for:
#101
It might be related to:
#43
since we currently just use .endsWith()
to check if a component name matches a path we generate some false positives like the above.
In it's current state the codemod transforms {{foo}}
always to {{this.foo}}
(skipping template-only components). It should transform {{foo}}
to {{@foo}}
instead if the property is not defined by the class of the codemod.
It may always transform to {{this.foo}}
if the component extends from another component cause parsing parent classes may be to complex. It should print a warning in that case.
Currently, we have the default value of dontAssumeThis
set to false
. This means that everything that the codemod couldn't find would be prefixed with this
There are a number of use cases where we wouldn't want to assume this
to be prefixed by default.
Eg:
{{foo bar=baz.biz/bang}}
converts to
{{foo bar=this.baz.biz/bang}}
In this case, baz
is not a property defined in the foo.js
component, instead, its an argument passed in from the consumer.
Also, for cases with data-*
selectors, they get prefixed with this
as well due to our default settings.
Suggestion: Set the dontAssumeThis
value to true
instead of false
I found a number of my templates failed with compilation errors when I ran this codemod on them. They were all failing due to the following scenario.
Notice all the arguments and attributes are placed side-by-side together with no spacing between them. This causes a template compilation error.
The issue seems to be specifically related to the positioning of the data-
attribute being first and the fact it doesn't have an assignment. The following two inputs transform with no issues:
{{not foo}}
becomes {{this.not this.foo}}
I came across this invalid transformation while running the codemod over some of my files. This is may be an issue with ember-template-recast but thought I'd raise first here anyway.
First image tag has no closing /
.
First image gets a closing </img>
tag which is invalid
The README file does not mention that ember serve
needs to run in the background for the codemod to be able to do its thing. It looks like #8 tried to fix this, but the MR has merge conflicts and changes other things too.
Before:
<a href="" class="theme-validation-toggle-details" {{action "toggleDetails"}} data-test-toggle-details>
After:
<a href="" class="theme-validation-toggle-details"="" {{action "toggleDetails"}}="" data-test-toggle-details>
Here's the full original file in case it's needed for debugging:
I ran npx ember-no-implicit-this-codemod http://localhost:4200 app/
and this is what happened...
to reproduce, https://github.com/skylines-project/skylines/tree/4af6a8173ccddd5339f79c2a44a97615b682231c/ember is the commit that I ran this on
(v-get this "courseTitle" "isInvalid")
ended up as (v-get this. "courseTitle" "isInvalid")
as it added a .
to this
when there was no property.
{{model}}
in route templates is transformed to {{this.model}}
but should be {{@model}}
in my opinion. At least if ember-source
is >= 3.14 and if the backing controller does not have a model
property.
integration tests currently fail :(
Having them fixed would be awesome :)
to run:
yarn test:integration
I am running into the same error as the Angle Bracket codemod when trying to run this:
ember-codemods/ember-angle-brackets-codemod#243
(node:79453) UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: Cannot read property 'entries' of undefined
at __puppeteer_evaluation_script__:9:50
at ExecutionContext._evaluateInternal (/Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/node_modules/puppeteer/lib/ExecutionContext.js:122:13)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async ExecutionContext.evaluate (/Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/node_modules/puppeteer/lib/ExecutionContext.js:48:12)
at async gatherTelemetry (/Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/node_modules/ember-codemods-telemetry-helpers/lib/gather/gather-telemetry.js:26:21)
at async /Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/bin/cli.js:9:3
-- ASYNC --
at ExecutionContext.<anonymous> (/Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/node_modules/puppeteer/lib/helper.js:111:15)
at DOMWorld.evaluate (/Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/node_modules/puppeteer/lib/DOMWorld.js:112:20)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
-- ASYNC --
at Frame.<anonymous> (/Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/node_modules/puppeteer/lib/helper.js:111:15)
at Page.evaluate (/Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/node_modules/puppeteer/lib/Page.js:833:43)
at Page.<anonymous> (/Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/node_modules/puppeteer/lib/helper.js:112:23)
at bridgeEvaluate (/Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/node_modules/ember-codemods-telemetry-helpers/lib/gather/gather-telemetry.js:66:17)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async gatherTelemetry (/Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/node_modules/ember-codemods-telemetry-helpers/lib/gather/gather-telemetry.js:26:21)
at async /Users/alafroscia/.npm/_npx/79453/lib/node_modules/ember-no-implicit-this-codemod/bin/cli.js:9:3
(node:79453) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:79453) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
The result is that the codemod can't be used.
Is it possible to run this codemod without telemetry data, the same way that the Angle Bracket codemod can?
This is more than likely an ember-template-recast bug but opening it here to start. It appears having a newline AFTER the as
keyword when yielding properties causes an invalid transform. Not to make the invalid transform you have to modify a property on the line. For example:
Notice the <MyComponent
has been duplicated inline and causes a template compile error due to invalid syntax.
If the input looks like the following with the yielded property on the same line as the as
, the transform works as expected
Currently if some property is found to NOT be a local property, block param, action, helper, component etc it's automatically assumed to be a local property and has this.
prepended to it. Personally I think this is too liberal an assumption and we can't always assume this. A simplified use case that didn't transform as I'd expect was the following:
// some-component JS definition
export default Component.extend({
foo: 'foo',
});
I'm not sure if we can ever deduce whether something should have an @
in front of it. But in the case where we can't accurately 100% know if it should have a this.
or @
in front of it I'd prefer if we didn't try to transform and instead just log out those ambiguous cases. We do similar in the angle bracket codemod with positional params and other ambiguous cases.
This logic is contained within the doesTokenNeedThis
function in helpers/plugin.js
.
At the end of this function we return true
where I think we should instead return false
. Worth noting that returning false
doesn't cause any of the tests to fail, they are still ๐.
So with this change my workflow to migrating a template would involve:
no-implicit-this
template-lint ruleImplicit this
fallback is deprecated in Ember canary: https://deprecations.emberjs.com/v3.x/#toc_this-property-fallback
While trying to address the deprecation in Ember Bootstrap I noticed that many tests were still relying on implicit this
fallback. The codemod does not support templates written with hbs
helper yet. So basically not support for tests yet. But for libraries like Ember Bootstrap with a huge test suite updating them by hand means a lot of work. Even after investing two hours to fix some of them, I still face 119 lint errors. Please find more details here: https://github.com/kaliber5/ember-bootstrap/pull/1421/files
Long story short: To address the deprecation in addons it would be very helpful if the codemod could support inline templates used in tests as well.
I've used the didInsert
modifier from @ember/render-modifiers
in some templates and they are getting replaced with this.didInsert
.
Not sure at what level this happens, this is as close to a simple case as I could get anything else I could think of to make it less complicated didn't have this issue.
{{#each something as |obj|}}
{{#if obj.foo}}
111
{{else}}
222
<div>
{{#if obj.foo}}
{{#if (eq obj.bar "foo")}}
333
{{else}}
444
{{/if}}
<span>
{{#if obj.foo}}
555
{{/if}}
</span>
{{else if obj.bar}}
666
{{else}}
777
{{/if}}
</div>
{{/if}}
{{/each}}
After running the codemod the else 777
section is completely removed.
I attempted to create a test to duplicate this, but it does not happen in the tests, so it may have something to do with the running server. In case that's the issue I created a reproduction repo at https://github.com/jrjohnson/reproduction-implicit-this-mod-nested (edit: fixed failing test / copy paste error)
We have a case where one of the helpers is driven by AST transform (build-time-helper) and hence it's not detected when the codemod is run. With a config option, it would open doors for handling such weird/custom usecases.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.