Code Monkey home page Code Monkey logo

ember-no-implicit-this-codemod's People

Contributors

dependabot-preview[bot] avatar dependabot[bot] avatar dfreeman avatar dustinsoftware avatar gitkrystan avatar jelhan avatar jrjohnson avatar mansona avatar mikek2252 avatar nullvoxpopuli avatar patocallaghan avatar rwjblue avatar scalvert avatar turbo87 avatar tylerturdenpants avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ember-no-implicit-this-codemod's Issues

Some properties not prefixed

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}}

RangeError: Maximum call stack size exceeded

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

Template-only component templates are not adjusted

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 incorrectly prefixed with 'this' for curly bracket components

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.

Error: Evaluation failed: TypeError: Cannot convert undefined or null to object

/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

{{rootURL}} changed to {{this.rootURL}}

Before:

    {{#link-to "index" class="navbar-brand"}}<img src="{{rootURL}}images/logo3.png">{{/link-to}}
  </div>

After:

{{#link-to "index" class="navbar-brand"}}<img src="{{this.rootURL}}images/logo3.png">{{/link-to}}
  </div>

Current github master (3df3c19) + current master of telemetry-helpers (as the currently released version breaks on Windows)

Codemod does nothing to a fresh ember-quickstart app

  1. Clone this repo at commit b06dccd
  2. Clone https://github.com/dustinsoftware/ember-quickstart-codemod. The old-school template has three uses of implicit this that need to be fixed.
  3. Start the ember server with ember serve in ember-quickstart-codemod
  4. Run node ./bin/telemetry.js http://localhost:4200, observe successful output
  5. Run node ./bin/cli.js no-implicit-this ~/ember-quickstart/app/. Observe that no templates are modified.

image

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' } }

Error on windows

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>

Codemod doesn't modify route templates with no controller

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.

Error running on macOS ARM

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.

Missing migrations

Before

<a href="https://dev.azure.com/{{ project }}/_build/latest?definitionId={{ build }}">
  <img src="https://dev.azure.com/{{ project }}/_apis/build/status/{{ pipeline }}" alt="{{ text }}" title="{{ text }}">
</a>

After

<a href="https://dev.azure.com/{{ this.project }}/_build/latest?definitionId={{ this.build }}">
  <img src="https://dev.azure.com/{{ this.project }}/_apis/build/status/{{ this.pipeline }}" alt="{{ text }}" title="{{ text }}">
</a>

Expected

<a href="https://dev.azure.com/{{ this.project }}/_build/latest?definitionId={{ this.build }}">
  <img src="https://dev.azure.com/{{ this.project }}/_apis/build/status/{{ this.pipeline }}" alt="{{ this.text }}" title="{{ this.text }}">
</a>

I'm not sure what happened here, but it seems that the text curlies were not converted properly

Source: https://github.com/rust-lang/crates.io

Multiple component invocations got this. added

Before:

{{nav/web-top-bar}}
{{nav/web-header}}
<div class="asdf">
  {{liquid-outlet}}
  {{liquid-modal}}
</div>

{{nav/web-footer}}

After:

{{this.nav/web-top-bar}}
{{this.nav/web-header}}
<div class="asdf">
  {{liquid-outlet}}
  {{this.liquid-modal}}
</div>

{{this.nav/web-footer}}

Current github master (3df3c19) + current master of telemetry-helpers (as the currently released version breaks on Windows)

Properties are overriding components/helpers

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.

Tests do not pass on Windows

Steps to repro:

  1. Clone the repo
  2. Restore packages with yarn
  3. Run yarn test
    image
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

Doesn't recognize Glimmer Components via runtime telemetry

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:

https://github.com/ember-codemods/ember-codemods-telemetry-helpers/blob/cf2bb9be57bd5cc454c73c61217db64d76c0dbed/lib/gather/analyze-ember-object.js#L158-L171

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

Transform to `{{@foo}}` if component class does not define the property

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.

default `dontAssumeThis` value to `true`

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

`data-` attribute positioning causes invalid transformation

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.

Before

<Select
  data-test-select
  @items={{foo}}
  @onSelectItem={{action "setValue"}}
  @selectedValue={{foo}}
/>

Expected

<Select
  data-test-select
  @items={{this.foo}}
  @onSelectItem={{action "setValue"}}
  @selectedValue={{this.foo}}
/>

Result

Notice all the arguments and attributes are placed side-by-side together with no spacing between them. This causes a template compilation error.

<Select
  data-test-select@items={{this.foo}}@onSelectItem={{action "setValue"}}@selectedValue={{this.foo}}
/>

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:

<Select
  data-test-select="true"
  @items={{this.foo}}
  @onSelectItem={{action "setValue"}}
  @selectedValue={{this.foo}}
/>

<Select
  @items={{this.foo}}
  @onSelectItem={{action "setValue"}}
  @selectedValue={{this.foo}}
  data-test-select
/>

Void element transforms to have a closing tag

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.

Before

First image tag has no closing /.

<img
 id="Preview"
 src="{{previewImageUrl}}"
 class="image"
>

<img
 id="Preview"
 src="{{previewImageUrl}}"
 class="image"
/>

Expected

<img
 id="Preview"
 src="{{this.previewImageUrl}}"
 class="image"
>

<img
 id="Preview"
 src="{{this.previewImageUrl}}"
 class="image"
/>

Result

First image gets a closing </img> tag which is invalid

<img
 id="Preview"
 src="{{this.previewImageUrl}}"
 class="image"
></img>

<img
 id="Preview"
 src="{{this.previewImageUrl}}"
 class="image"
/>

README is missing `ember serve`

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.

Unnecessary `=""` added

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:

gh-theme-error-li.hbs
<a href="" class="theme-validation-toggle-details" {{action "toggleDetails"}} data-test-toggle-details>
    <div class="theme-validation-type-label"></div>
    <div class="flex items-center flex-auto">
        <h4 class="theme-validation-rule-text">
            {{{this.error.rule}}}
        </h4>
        <div class="theme-validation-rule-icon">
            {{#if this.showDetails}}
                {{svg-jar "arrow-down"}}
            {{else}}
                {{svg-jar "arrow-right"}}
            {{/if}}
        </div>
    </div>
</a>

{{#if this.showDetails}}
    <p class="theme-validation-details">
        {{{this.error.details}}}
    </p>
    {{#if this.error.failures}}
        <div class="theme-validation-list">
            <h6>Affected files:</h6>
            <ul>
                {{#each this.error.failures as |failure|}}
                    <li><code>{{failure.ref}}</code>{{#if failure.message}}: {{failure.message}}{{/if}}</li>
                {{/each}}
            </ul>
        </div>
    {{/if}}
{{/if}}

Make it work!

  • Initialize codemod-cli project
  • Add puppeteer setup to gather list of helpers/components/modifiers available in the application
  • Add use ember-template-recast to transform templates

Transforms this into this.

(v-get this "courseTitle" "isInvalid") ended up as (v-get this. "courseTitle" "isInvalid") as it added a . to this when there was no property.

Error Thrown during Telemetry Gathering

I am running into the same error as the Angle Bracket codemod when trying to run this:

ember-codemods/ember-angle-brackets-codemod#243

Stack Trace

(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?

[Bug] Newline after `as` causes an invalid transform

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:

Input

<MyComponent @someArg={{value}} as
|myComponent|>
</MyComponent>

Expected output

<MyComponent @someArg={{this.value}} as
|myComponent|>
</MyComponent>

Actual output

<MyComponent @someArg={{this.value}} <MyComponent @someArg={{this.value}} as
|myComponent|>
</MyComponent>

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

<MyComponent @someArg={{value}} as |myComponent|>
</MyComponent>

Codemod is too liberal at appending `this.`

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',
});
<!-- some-component invocation -->
<SomeComponent
  @bar="bar"
/>

<!-- some-component HBS definition -->
<!-- Before: the codemod runs -->
<!-- Here we are using the "local" foo property and the passed in "bar" argument -->
{{foo}}
{{bar}}

<!-- After: the codemod runs -->
{{this.foo}}
{{this.bar}}

<!-- In reality what it should be -->
{{this.foo}}
{{@bar}}

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.

function doesTokenNeedThis(token, { components, helpers, scopedParams }, runtimeData) {
if (ARGLESS_BUILTINS.includes(token)) {
return false;
}
let isBlockParam = scopedParams.includes(token);
if (isBlockParam) {
return false;
}
let { computedProperties, ownActions, ownProperties } = runtimeData;
let isComputed = (computedProperties || []).includes(token);
let isAction = (ownActions || []).includes(token);
let isProperty = (ownProperties || []).includes(token);
let needsThis = isComputed || isAction || isProperty;
if (needsThis) {
return true;
}
let isComponent = components.find(path => path.endsWith(token));
if (isComponent) {
return false;
}
let isHelper = helpers.find(path => path.endsWith(token));
if (isHelper) {
return false;
}
return true;

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:

  1. Run this codemod on said template
  2. turn on no-implicit-this template-lint rule
  3. Fix up the ambiguous errors on a case-by-case basis

Support inline templates with hbs helper

Implicit 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.

Drops deeply nested {{else}}

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)

Support a config option to augment the telemetry data

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.