From d2b8b58b5777708e955e2c1c90531db8a35819b5 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Thu, 11 Feb 2021 03:03:49 -0800 Subject: [PATCH] [FEATURE modernized-built-in-components] Extract shared code Refactor to extra shared code into internal component to pave way for implementing with the new infrastructure. Part of #19270 --- packages/@ember/-internals/glimmer/index.ts | 5 +- .../lib/component-managers/internal.ts | 88 -- .../glimmer/lib/components/-textarea.ts | 103 ++ .../glimmer/lib/components/abstract-input.ts | 321 +++++++ .../glimmer/lib/components/input.ts | 900 ++---------------- .../glimmer/lib/components/internal.ts | 530 ++++++++++- .../glimmer/lib/components/textarea.ts | 143 ++- .../-internals/glimmer/lib/setup-registry.ts | 17 +- .../glimmer/lib/templates/input.hbs | 2 +- .../glimmer/lib/templates/textarea.hbs | 2 +- 10 files changed, 1114 insertions(+), 997 deletions(-) delete mode 100644 packages/@ember/-internals/glimmer/lib/component-managers/internal.ts create mode 100644 packages/@ember/-internals/glimmer/lib/components/-textarea.ts create mode 100644 packages/@ember/-internals/glimmer/lib/components/abstract-input.ts diff --git a/packages/@ember/-internals/glimmer/index.ts b/packages/@ember/-internals/glimmer/index.ts index d756909be67..c8a801895ed 100644 --- a/packages/@ember/-internals/glimmer/index.ts +++ b/packages/@ember/-internals/glimmer/index.ts @@ -366,9 +366,10 @@ export { templateFactory as template, templateCacheCounters } from '@glimmer/opc export { default as RootTemplate } from './lib/templates/root'; export { default as Checkbox } from './lib/components/checkbox'; export { default as TextField } from './lib/components/text-field'; -export { default as TextArea } from './lib/components/textarea'; +export { default as TextArea } from './lib/components/-textarea'; export { default as LinkComponent } from './lib/components/link-to'; -export { default as Input, TextareaComponent as Textarea } from './lib/components/input'; +export { default as Input } from './lib/components/input'; +export { default as Textarea } from './lib/components/textarea'; export { default as Component } from './lib/component'; export { default as Helper, helper } from './lib/helper'; export { SafeString, escapeExpression, htmlSafe, isHTMLSafe } from './lib/utils/string'; diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/internal.ts b/packages/@ember/-internals/glimmer/lib/component-managers/internal.ts deleted file mode 100644 index d6636a3ee5e..00000000000 --- a/packages/@ember/-internals/glimmer/lib/component-managers/internal.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Owner } from '@ember/-internals/owner'; -import { assert } from '@ember/debug'; -import { - CapturedNamedArguments, - Destroyable, - DynamicScope, - Environment, - InternalComponentCapabilities, - InternalComponentManager, - VMArguments, - WithCreateInstance, -} from '@glimmer/interfaces'; -import { createConstRef, isConstRef, Reference, valueForRef } from '@glimmer/reference'; - -const CAPABILITIES: InternalComponentCapabilities = { - dynamicLayout: false, - dynamicTag: false, - prepareArgs: false, - createArgs: true, - attributeHook: false, - elementHook: false, - createCaller: true, - dynamicScope: false, - updateHook: false, - createInstance: true, - wrapped: false, - willDestroy: false, - hasSubOwner: false, -}; - -export interface InternalComponentState { - env: Environment; - instance: Destroyable; -} - -export interface EmberInternalComponentConstructor { - new (owner: Owner, args: CapturedNamedArguments, caller: unknown): Destroyable; -} - -export default class InternalManager - implements - InternalComponentManager, - WithCreateInstance { - constructor(private ComponentClass: EmberInternalComponentConstructor, private name: string) {} - - getCapabilities(): InternalComponentCapabilities { - return CAPABILITIES; - } - - create( - owner: Owner, - _definition: unknown, - args: VMArguments, - env: Environment, - _dynamicScope: DynamicScope, - caller: Reference - ): InternalComponentState { - assert('caller must be const', isConstRef(caller)); - - assert( - `The ${this.name} component does not take any positional arguments`, - args.positional.length === 0 - ); - - let { ComponentClass } = this; - let instance = new ComponentClass(owner, args.named.capture(), valueForRef(caller)); - - return { env, instance }; - } - - didCreate(): void {} - didUpdate(): void {} - - didRenderLayout(): void {} - didUpdateLayout(): void {} - - getDebugName(): string { - return this.name; - } - - getSelf({ instance }: InternalComponentState): Reference { - return createConstRef(instance, 'this'); - } - - getDestroyable(state: InternalComponentState): Destroyable { - return state.instance; - } -} diff --git a/packages/@ember/-internals/glimmer/lib/components/-textarea.ts b/packages/@ember/-internals/glimmer/lib/components/-textarea.ts new file mode 100644 index 00000000000..00473ea09b7 --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/components/-textarea.ts @@ -0,0 +1,103 @@ +/** +@module @ember/component +*/ +import { CoreObject } from '@ember/-internals/runtime'; +import { TextSupport } from '@ember/-internals/views'; +import { EMBER_MODERNIZED_BUILT_IN_COMPONENTS } from '@ember/canary-features'; +import { deprecate } from '@ember/debug'; +import Component from '../component'; +import layout from '../templates/empty'; + +/** + The internal representation used for `Textarea` invocations. + + @class TextArea + @extends Component + @see {Ember.Templates.components.Textarea} + @uses Ember.TextSupport + @public +*/ +const TextArea = Component.extend(TextSupport, { + classNames: ['ember-text-area'], + + layout, + + tagName: 'textarea', + attributeBindings: [ + 'rows', + 'cols', + 'name', + 'selectionEnd', + 'selectionStart', + 'autocomplete', + 'wrap', + 'lang', + 'dir', + 'value', + ], + rows: null, + cols: null, +}); + +TextArea.toString = () => '@ember/component/text-area'; + +if (EMBER_MODERNIZED_BUILT_IN_COMPONENTS) { + Object.defineProperty(TextArea, '_wasReopened', { + configurable: true, + enumerable: false, + writable: true, + value: false, + }); + + Object.defineProperty(TextArea, 'reopen', { + configurable: true, + enumerable: false, + writable: true, + value: function reopen(this: typeof TextArea, ...args: unknown[]): unknown { + if (this === TextArea) { + deprecate( + 'Reopening Ember.TextArea is deprecated. Consider implementing your own ' + + 'wrapper component or create a custom subclass.', + false, + { + id: 'ember.built-in-components.reopen', + for: 'ember-source', + since: {}, + until: '4.0.0', + } + ); + + TextArea._wasReopened = true; + } + + return CoreObject.reopen.call(this, ...args); + }, + }); + + Object.defineProperty(TextArea, 'reopenClass', { + configurable: true, + enumerable: false, + writable: true, + value: function reopenClass(this: typeof TextArea, ...args: unknown[]): unknown { + if (this === TextArea) { + deprecate( + 'Reopening Ember.TextArea is deprecated. Consider implementing your own ' + + 'wrapper component or create a custom subclass.', + false, + { + id: 'ember.built-in-components.reopen', + for: 'ember-source', + since: {}, + until: '4.0.0', + } + ); + + TextArea._wasReopened = true; + } + + return CoreObject.reopenClass.call(this, ...args); + }, + }); +} + +export default TextArea; diff --git a/packages/@ember/-internals/glimmer/lib/components/abstract-input.ts b/packages/@ember/-internals/glimmer/lib/components/abstract-input.ts new file mode 100644 index 00000000000..cc08b53de5e --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/components/abstract-input.ts @@ -0,0 +1,321 @@ +import { tracked } from '@ember/-internals/metal'; +import { TargetActionSupport } from '@ember/-internals/runtime'; +import { TextSupport } from '@ember/-internals/views'; +import { EMBER_MODERNIZED_BUILT_IN_COMPONENTS } from '@ember/canary-features'; +import { assert, deprecate } from '@ember/debug'; +import { JQUERY_INTEGRATION, SEND_ACTION } from '@ember/deprecated-features'; +import { action } from '@ember/object'; +import { isConstRef, isUpdatableRef, Reference, updateRef, valueForRef } from '@glimmer/reference'; +import Component from '../component'; +import InternalComponent, { + DeprecatingInternalComponent, + EventListener, + handleDeprecatedArguments, + handleDeprecatedAttributeArguments, + handleDeprecatedEventArguments, + InternalComponentConstructor, + jQueryEventShim, +} from './internal'; + +const UNINITIALIZED: unknown = Object.freeze({}); + +type VirtualEventListener = (value: string, event: Event) => void; + +function elementForEvent(event: Event): HTMLInputElement | HTMLTextAreaElement { + assert( + '[BUG] event target must be an or