How to use checkAndWarnForMutatedStyle method in Playwright Internal

Best JavaScript code snippet using playwright-internal

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

ReactDOMComponent.js

Source: ReactDOMComponent.js Github

copy
1/* */ 
2(function(process) {
3  'use strict';
4  var CSSPropertyOperations = require("./CSSPropertyOperations");
5  var DOMProperty = require("./DOMProperty");
6  var DOMPropertyOperations = require("./DOMPropertyOperations");
7  var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter");
8  var ReactComponentBrowserEnvironment = require("./ReactComponentBrowserEnvironment");
9  var ReactMount = require("./ReactMount");
10  var ReactMultiChild = require("./ReactMultiChild");
11  var ReactPerf = require("./ReactPerf");
12  var assign = require("./Object.assign");
13  var escapeTextContentForBrowser = require("./escapeTextContentForBrowser");
14  var invariant = require("./invariant");
15  var isEventSupported = require("./isEventSupported");
16  var keyOf = require("./keyOf");
17  var shallowEqual = require("./shallowEqual");
18  var validateDOMNesting = require("./validateDOMNesting");
19  var warning = require("./warning");
20  var deleteListener = ReactBrowserEventEmitter.deleteListener;
21  var listenTo = ReactBrowserEventEmitter.listenTo;
22  var registrationNameModules = ReactBrowserEventEmitter.registrationNameModules;
23  var CONTENT_TYPES = {
24    'string': true,
25    'number': true
26  };
27  var STYLE = keyOf({style: null});
28  var ELEMENT_NODE_TYPE = 1;
29  var styleMutationWarning = {};
30  function checkAndWarnForMutatedStyle(style1, style2, component) {
31    if (style1 == null || style2 == null) {
32      return ;
33    }
34    if (shallowEqual(style1, style2)) {
35      return ;
36    }
37    var componentName = component._tag;
38    var owner = component._currentElement._owner;
39    var ownerName;
40    if (owner) {
41      ownerName = owner.getName();
42    }
43    var hash = ownerName + '|' + componentName;
44    if (styleMutationWarning.hasOwnProperty(hash)) {
45      return ;
46    }
47    styleMutationWarning[hash] = true;
48    'production' !== process.env.NODE_ENV ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', JSON.stringify(style1), JSON.stringify(style2)) : undefined;
49  }
50  var BackendIDOperations = null;
51  function assertValidProps(component, props) {
52    if (!props) {
53      return ;
54    }
55    if ('production' !== process.env.NODE_ENV) {
56      if (voidElementTags[component._tag]) {
57        'production' !== process.env.NODE_ENV ? warning(props.children == null && props.dangerouslySetInnerHTML == null, '%s is a void element tag and must not have `children` or ' + 'use `props.dangerouslySetInnerHTML`.', component._tag) : undefined;
58      }
59    }
60    if (props.dangerouslySetInnerHTML != null) {
61      !(props.children == null) ? 'production' !== process.env.NODE_ENV ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : invariant(false) : undefined;
62      !(typeof props.dangerouslySetInnerHTML === 'object' && '__html' in props.dangerouslySetInnerHTML) ? 'production' !== process.env.NODE_ENV ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' + 'for more information.') : invariant(false) : undefined;
63    }
64    if ('production' !== process.env.NODE_ENV) {
65      'production' !== process.env.NODE_ENV ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : undefined;
66      'production' !== process.env.NODE_ENV ? warning(!props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : undefined;
67    }
68    !(props.style == null || typeof props.style === 'object') ? 'production' !== process.env.NODE_ENV ? invariant(false, 'The `style` prop expects a mapping from style properties to values, ' + 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' + 'using JSX.') : invariant(false) : undefined;
69  }
70  function enqueuePutListener(id, registrationName, listener, transaction) {
71    if ('production' !== process.env.NODE_ENV) {
72      'production' !== process.env.NODE_ENV ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : undefined;
73    }
74    var container = ReactMount.findReactContainerForID(id);
75    if (container) {
76      var doc = container.nodeType === ELEMENT_NODE_TYPE ? container.ownerDocument : container;
77      listenTo(registrationName, doc);
78    }
79    transaction.getReactMountReady().enqueue(putListener, {
80      id: id,
81      registrationName: registrationName,
82      listener: listener
83    });
84  }
85  function putListener() {
86    var listenerToPut = this;
87    ReactBrowserEventEmitter.putListener(listenerToPut.id, listenerToPut.registrationName, listenerToPut.listener);
88  }
89  var omittedCloseTags = {
90    'area': true,
91    'base': true,
92    'br': true,
93    'col': true,
94    'embed': true,
95    'hr': true,
96    'img': true,
97    'input': true,
98    'keygen': true,
99    'link': true,
100    'meta': true,
101    'param': true,
102    'source': true,
103    'track': true,
104    'wbr': true
105  };
106  var newlineEatingTags = {
107    'listing': true,
108    'pre': true,
109    'textarea': true
110  };
111  var voidElementTags = assign({'menuitem': true}, omittedCloseTags);
112  var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/;
113  var validatedTagCache = {};
114  var hasOwnProperty = ({}).hasOwnProperty;
115  function validateDangerousTag(tag) {
116    if (!hasOwnProperty.call(validatedTagCache, tag)) {
117      !VALID_TAG_REGEX.test(tag) ? 'production' !== process.env.NODE_ENV ? invariant(false, 'Invalid tag: %s', tag) : invariant(false) : undefined;
118      validatedTagCache[tag] = true;
119    }
120  }
121  function processChildContext(context, inst) {
122    if ('production' !== process.env.NODE_ENV) {
123      context = assign({}, context);
124      var info = context[validateDOMNesting.ancestorInfoContextKey];
125      context[validateDOMNesting.ancestorInfoContextKey] = validateDOMNesting.updatedAncestorInfo(info, inst._tag, inst);
126    }
127    return context;
128  }
129  function ReactDOMComponent(tag) {
130    validateDangerousTag(tag);
131    this._tag = tag;
132    this._renderedChildren = null;
133    this._previousStyle = null;
134    this._previousStyleCopy = null;
135    this._rootNodeID = null;
136  }
137  ReactDOMComponent.displayName = 'ReactDOMComponent';
138  ReactDOMComponent.Mixin = {
139    construct: function(element) {
140      this._currentElement = element;
141    },
142    mountComponent: function(rootID, transaction, context) {
143      this._rootNodeID = rootID;
144      assertValidProps(this, this._currentElement.props);
145      if ('production' !== process.env.NODE_ENV) {
146        if (context[validateDOMNesting.ancestorInfoContextKey]) {
147          validateDOMNesting(this._tag, this, context[validateDOMNesting.ancestorInfoContextKey]);
148        }
149      }
150      var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction);
151      var tagContent = this._createContentMarkup(transaction, context);
152      if (!tagContent && omittedCloseTags[this._tag]) {
153        return tagOpen + '/>';
154      }
155      return tagOpen + '>' + tagContent + '</' + this._tag + '>';
156    },
157    _createOpenTagMarkupAndPutListeners: function(transaction) {
158      var props = this._currentElement.props;
159      var ret = '<' + this._tag;
160      for (var propKey in props) {
161        if (!props.hasOwnProperty(propKey)) {
162          continue;
163        }
164        var propValue = props[propKey];
165        if (propValue == null) {
166          continue;
167        }
168        if (registrationNameModules.hasOwnProperty(propKey)) {
169          enqueuePutListener(this._rootNodeID, propKey, propValue, transaction);
170        } else {
171          if (propKey === STYLE) {
172            if (propValue) {
173              if ('production' !== process.env.NODE_ENV) {
174                this._previousStyle = propValue;
175              }
176              propValue = this._previousStyleCopy = assign({}, props.style);
177            }
178            propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
179          }
180          var markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
181          if (markup) {
182            ret += ' ' + markup;
183          }
184        }
185      }
186      if (transaction.renderToStaticMarkup) {
187        return ret;
188      }
189      var markupForID = DOMPropertyOperations.createMarkupForID(this._rootNodeID);
190      return ret + ' ' + markupForID;
191    },
192    _createContentMarkup: function(transaction, context) {
193      var ret = '';
194      var props = this._currentElement.props;
195      var innerHTML = props.dangerouslySetInnerHTML;
196      if (innerHTML != null) {
197        if (innerHTML.__html != null) {
198          ret = innerHTML.__html;
199        }
200      } else {
201        var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
202        var childrenToUse = contentToUse != null ? null : props.children;
203        if (contentToUse != null) {
204          ret = escapeTextContentForBrowser(contentToUse);
205        } else if (childrenToUse != null) {
206          var mountImages = this.mountChildren(childrenToUse, transaction, processChildContext(context, this));
207          ret = mountImages.join('');
208        }
209      }
210      if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') {
211        return '\n' + ret;
212      } else {
213        return ret;
214      }
215    },
216    receiveComponent: function(nextElement, transaction, context) {
217      var prevElement = this._currentElement;
218      this._currentElement = nextElement;
219      this.updateComponent(transaction, prevElement, nextElement, context);
220    },
221    updateComponent: function(transaction, prevElement, nextElement, context) {
222      assertValidProps(this, this._currentElement.props);
223      this._updateDOMProperties(prevElement.props, transaction);
224      this._updateDOMChildren(prevElement.props, transaction, processChildContext(context, this));
225    },
226    _updateDOMProperties: function(lastProps, transaction) {
227      var nextProps = this._currentElement.props;
228      var propKey;
229      var styleName;
230      var styleUpdates;
231      for (propKey in lastProps) {
232        if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey)) {
233          continue;
234        }
235        if (propKey === STYLE) {
236          var lastStyle = this._previousStyleCopy;
237          for (styleName in lastStyle) {
238            if (lastStyle.hasOwnProperty(styleName)) {
239              styleUpdates = styleUpdates || {};
240              styleUpdates[styleName] = '';
241            }
242          }
243          this._previousStyleCopy = null;
244        } else if (registrationNameModules.hasOwnProperty(propKey)) {
245          if (lastProps[propKey]) {
246            deleteListener(this._rootNodeID, propKey);
247          }
248        } else if (DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) {
249          BackendIDOperations.deletePropertyByID(this._rootNodeID, propKey);
250        }
251      }
252      for (propKey in nextProps) {
253        var nextProp = nextProps[propKey];
254        var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps[propKey];
255        if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp) {
256          continue;
257        }
258        if (propKey === STYLE) {
259          if (nextProp) {
260            if ('production' !== process.env.NODE_ENV) {
261              checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);
262              this._previousStyle = nextProp;
263            }
264            nextProp = this._previousStyleCopy = assign({}, nextProp);
265          } else {
266            this._previousStyleCopy = null;
267          }
268          if (lastProp) {
269            for (styleName in lastProp) {
270              if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
271                styleUpdates = styleUpdates || {};
272                styleUpdates[styleName] = '';
273              }
274            }
275            for (styleName in nextProp) {
276              if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
277                styleUpdates = styleUpdates || {};
278                styleUpdates[styleName] = nextProp[styleName];
279              }
280            }
281          } else {
282            styleUpdates = nextProp;
283          }
284        } else if (registrationNameModules.hasOwnProperty(propKey)) {
285          if (nextProp) {
286            enqueuePutListener(this._rootNodeID, propKey, nextProp, transaction);
287          } else if (lastProp) {
288            deleteListener(this._rootNodeID, propKey);
289          }
290        } else if (DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) {
291          BackendIDOperations.updatePropertyByID(this._rootNodeID, propKey, nextProp);
292        }
293      }
294      if (styleUpdates) {
295        BackendIDOperations.updateStylesByID(this._rootNodeID, styleUpdates);
296      }
297    },
298    _updateDOMChildren: function(lastProps, transaction, context) {
299      var nextProps = this._currentElement.props;
300      var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
301      var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
302      var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;
303      var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;
304      var lastChildren = lastContent != null ? null : lastProps.children;
305      var nextChildren = nextContent != null ? null : nextProps.children;
306      var lastHasContentOrHtml = lastContent != null || lastHtml != null;
307      var nextHasContentOrHtml = nextContent != null || nextHtml != null;
308      if (lastChildren != null && nextChildren == null) {
309        this.updateChildren(null, transaction, context);
310      } else if (lastHasContentOrHtml && !nextHasContentOrHtml) {
311        this.updateTextContent('');
312      }
313      if (nextContent != null) {
314        if (lastContent !== nextContent) {
315          this.updateTextContent('' + nextContent);
316        }
317      } else if (nextHtml != null) {
318        if (lastHtml !== nextHtml) {
319          BackendIDOperations.updateInnerHTMLByID(this._rootNodeID, nextHtml);
320        }
321      } else if (nextChildren != null) {
322        this.updateChildren(nextChildren, transaction, context);
323      }
324    },
325    unmountComponent: function() {
326      this.unmountChildren();
327      ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
328      ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
329      this._rootNodeID = null;
330    }
331  };
332  ReactPerf.measureMethods(ReactDOMComponent, 'ReactDOMComponent', {
333    mountComponent: 'mountComponent',
334    updateComponent: 'updateComponent'
335  });
336  assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);
337  ReactDOMComponent.injection = {injectIDOperations: function(IDOperations) {
338      ReactDOMComponent.BackendIDOperations = BackendIDOperations = IDOperations;
339    }};
340  module.exports = ReactDOMComponent;
341})(require("process"));
342
Full Screen

Component.js

Source: Component.js Github

copy
1'use strict';
2
3// TODO: validate children elements (or parents?). Ex: <badge> can only be a child of
4//  - buttonLockup
5//  - header
6//  - lockup
7//  - overlay
8//  - row
9//  - text
10//  - title
11
12// TODO: validate CSS props. Only some are valid
13var __DEV__ = process.env.NODE_ENV !== 'production';
14
15var CSSPropertyOperations = require('react/lib/CSSPropertyOperations');
16var DOMProperty = require('react/lib/DOMProperty');
17var DOMPropertyOperations = require('react/lib/DOMPropertyOperations');
18// var EventConstants = require('react/lib/EventConstants');
19var EventEmitter = require('./EventEmitter');
20var IDOperations = require('./IDOperations');
21var MultiChild = require('react/lib/ReactMultiChild');
22var Perf = require('react/lib/ReactPerf');
23var UpdateQueue = require('react/lib/ReactUpdateQueue');
24
25var assign = require('react/lib/Object.assign');
26var escapeTextContentForBrowser = require('react/lib/escapeTextContentForBrowser');
27var invariant = require('fbjs/lib/invariant');
28var isEventSupported = require('react/lib/isEventSupported');
29var keyOf = require('fbjs/lib/keyOf');
30var setInnerHTML = require('react/lib/setInnerHTML');
31var setTextContent = require('react/lib/setTextContent');
32var shallowEqual = require('fbjs/lib/shallowEqual');
33var validateDOMNesting = require('react/lib/validateDOMNesting');
34var warning = require('fbjs/lib/warning');
35
36var hasOwnProperty = require('has-own-prop');
37
38var Mount = require('./Mount');
39
40
41var ELEMENT_NODE_TYPE = 1;
42
43// For quickly matching children type, to test if can be treated as content.
44var CONTENT_TYPES = {
45  'string': true,
46  'number': true
47};
48
49var STYLE = keyOf({
50  'style': null
51});
52
53var COMPONENT_CLASSES = {
54  menubar: require('./menuBar')
55};
56
57function getDeclarationErrorAddendum(internalInstance) {
58  if (internalInstance) {
59    var owner = internalInstance._currentElement._owner || null;
60    if (owner) {
61      var name = owner.getName();
62      if (name) {
63        return ' This DOM node was rendered by `' + name + '`.';
64      }
65    }
66  }
67  return '';
68}
69
70
71function legacyGetDOMNode() {
72  if (__DEV__) {
73    var component = this._reactInternalComponent;
74    warning(
75      false,
76      'ReactTVMLComponent: Do not access .getDOMNode() of a DOM node; ' +
77      'instead, use the node directly.%s',
78      getDeclarationErrorAddendum(component)
79    );
80  }
81  return this;
82}
83
84function legacyIsMounted() {
85  var component = this._reactInternalComponent;
86  if (__DEV__) {
87    warning(
88      false,
89      'ReactTVMLComponent: Do not access .isMounted() of a DOM node.%s',
90      getDeclarationErrorAddendum(component)
91    );
92  }
93  return !!component;
94}
95
96function legacySetStateEtc() {
97  if (__DEV__) {
98    var component = this._reactInternalComponent;
99    warning(
100      false,
101      'ReactTVMLComponent: Do not access .setState(), .replaceState(), or ' +
102      '.forceUpdate() of a DOM node. This is a no-op.%s',
103      getDeclarationErrorAddendum(component)
104    );
105  }
106}
107
108function legacySetProps(partialProps, callback) {
109  var component = this._reactInternalComponent;
110  if (__DEV__) {
111    warning(
112      false,
113      'ReactTVMLComponent: Do not access .setProps() of a DOM node. ' +
114      'Instead, call ReactDOM.render again at the top level.%s',
115      getDeclarationErrorAddendum(component)
116    );
117  }
118  if (!component) {
119    return;
120  }
121  UpdateQueue.enqueueSetPropsInternal(component, partialProps);
122  if (callback) {
123    UpdateQueue.enqueueCallbackInternal(component, callback);
124  }
125}
126
127function legacyReplaceProps(partialProps, callback) {
128  var component = this._reactInternalComponent;
129  if (__DEV__) {
130    warning(
131      false,
132      'ReactTVMLComponent: Do not access .replaceProps() of a DOM node. ' +
133      'Instead, call ReactDOM.render again at the top level.%s',
134      getDeclarationErrorAddendum(component)
135    );
136  }
137  if (!component) {
138    return;
139  }
140  UpdateQueue.enqueueReplacePropsInternal(component, partialProps);
141  if (callback) {
142    UpdateQueue.enqueueCallbackInternal(component, callback);
143  }
144}
145
146var styleMutationWarning = {};
147
148function checkAndWarnForMutatedStyle(style1, style2, component) {
149  if (style1 == null || style2 == null) {
150    return;
151  }
152  if (shallowEqual(style1, style2)) {
153    return;
154  }
155
156  var componentName = component._tag;
157  var owner = component._currentElement._owner;
158  var ownerName;
159  if (owner) {
160    ownerName = owner.getName();
161  }
162
163  var hash = ownerName + '|' + componentName;
164
165  if (hasOwnProperty(styleMutationWarning, hash)) {
166    return;
167  }
168
169  styleMutationWarning[hash] = true;
170
171  warning(
172    false,
173    '`%s` was passed a style object that has previously been mutated. ' +
174    'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' +
175    'the `render` %s. Previous style: %s. Mutated style: %s.',
176    componentName,
177    owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>',
178    JSON.stringify(style1),
179    JSON.stringify(style2)
180  );
181}
182
183/**
184 * @param {object} component
185 * @param {?object} props
186 */
187function assertValidProps(component, props) {
188  if (!props) {
189    return;
190  }
191  // Note the use of `==` which checks for null or undefined.
192  if (__DEV__) {
193    if (voidElementTags[component._tag]) {
194      warning(
195        props.children == null && props.dangerouslySetInnerHTML == null,
196        '%s is a void element tag and must not have `children` or ' +
197        'use `props.dangerouslySetInnerHTML`.%s',
198        component._tag,
199        component._currentElement._owner ?
200          ' Check the render method of ' +
201          component._currentElement._owner.getName() + '.' :
202          ''
203      );
204    }
205  }
206  if (props.dangerouslySetInnerHTML != null) {
207    invariant(
208      props.children == null,
209      'Can only set one of `children` or `props.dangerouslySetInnerHTML`.'
210    );
211    invariant(
212      typeof props.dangerouslySetInnerHTML === 'object' &&
213      '__html' in props.dangerouslySetInnerHTML,
214      '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +
215      'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' +
216      'for more information.'
217    );
218  }
219  if (__DEV__) {
220    warning(
221      props.innerHTML == null,
222      'Directly setting property `innerHTML` is not permitted. ' +
223      'For more information, lookup documentation on `dangerouslySetInnerHTML`.'
224    );
225    warning(
226      !props.contentEditable || props.children == null,
227      'A component is `contentEditable` and contains `children` managed by ' +
228      'React. It is now your responsibility to guarantee that none of ' +
229      'those nodes are unexpectedly modified or duplicated. This is ' +
230      'probably not intentional.'
231    );
232  }
233  invariant(
234    props.style == null || typeof props.style === 'object',
235    'The `style` prop expects a mapping from style properties to values, ' +
236    'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' +
237    'using JSX.%s',
238     getDeclarationErrorAddendum(component)
239  );
240}
241
242function enqueuePutListener(id, registrationName, listener, transaction) {
243  var container = Mount.findReactContainerForID(id);
244  if (container) {
245    var doc = container.nodeType === ELEMENT_NODE_TYPE ? container.ownerDocument : container;
246    EventEmitter.listenTo(registrationName, doc);
247  }
248  transaction.getReactMountReady().enqueue(putListener, {
249    id: id,
250    registrationName: registrationName,
251    listener: listener
252  });
253}
254
255function putListener(id, registrationName, listener, transaction) {
256  // TODO check if tvml registers events the same way as listenTo
257  // TODO I'm not sure we can register events in `document` and delegate
258  EventEmitter.EventEmitter.listenTo(registrationName, Mount.findReactContainerForID(id));
259
260  transaction.getReactMountReady().enqueue(putListener, {
261    id: id,
262    registrationName: registrationName,
263    listener: listener,
264  });
265
266  // if (container) {
267  //   var doc = container.nodeType === ELEMENT_NODE_TYPE ?
268  //     container.ownerDocument :
269  //     container;
270  //   EventEmitter.listenTo(registrationName, doc);
271  // }
272}
273
274function putListener() {
275  var listenerToPut = this;
276  EventEmitter.putListener(
277    listenerToPut.id,
278    listenerToPut.registrationName,
279    listenerToPut.listener
280  );
281}
282
283// There are so many media events, it makes sense to just
284// maintain a list rather than create a `trapBubbledEvent` for each
285var mediaEvents = {
286  // topAbort: 'abort',
287  // topCanPlay: 'canplay',
288  // topCanPlayThrough: 'canplaythrough',
289  // topDurationChange: 'durationchange',
290  // topEmptied: 'emptied',
291  // topEncrypted: 'encrypted',
292  // topEnded: 'ended',
293  // topError: 'error',
294  // topLoadedData: 'loadeddata',
295  // topLoadedMetadata: 'loadedmetadata',
296  // topLoadStart: 'loadstart',
297  // topPause: 'pause',
298  // topPlay: 'play',
299  // topPlaying: 'playing',
300  // topProgress: 'progress',
301  // topRateChange: 'ratechange',
302  // topSeeked: 'seeked',
303  // topSeeking: 'seeking',
304  // topStalled: 'stalled',
305  // topSuspend: 'suspend',
306  // topTimeUpdate: 'timeupdate',
307  // topVolumeChange: 'volumechange',
308  // topWaiting: 'waiting',
309};
310
311function postUpdateSelectWrapper() {
312  DOMSelect.postUpdateWrapper(this);
313}
314
315// For HTML, certain tags should omit their close tag. We keep a whitelist for
316// those special cased tags.
317var omittedCloseTags = {
318  'badge': true,
319  'decorationImage': true,
320  'fullscreenImg': true,
321  'heroImg': true,
322  'img': true,
323  'ratingBadge': true,
324  'asset': true,
325  'monogram': true
326};
327
328var newlineEatingTags = {
329  // 'listing': true,
330  // 'pre': true,
331  // 'textarea': true,
332};
333
334// For HTML, certain tags cannot have children. This has the same purpose as
335// `omittedCloseTags` except that `menuitem` should still have its closing tag.
336var voidElementTags = assign({
337}, omittedCloseTags);
338
339// We accept any tag to be rendered but since this gets injected into arbitrary
340// HTML, we want to make sure that it's a safe tag.
341// http://www.w3.org/TR/REC-xml/#NT-Name
342
343var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
344var validatedTagCache = {};
345
346function validateDangerousTag(tag) {
347  if (!hasOwnProperty(validatedTagCache, tag)) {
348    invariant(VALID_TAG_REGEX.test(tag), 'Invalid tag: %s', tag);
349    validatedTagCache[tag] = true;
350  }
351}
352
353function processChildContext(context, inst) {
354  if (__DEV__) {
355    // Pass down our tag name to child components for validation purposes
356    context = assign({}, context);
357    var info = context[validateDOMNesting.ancestorInfoContextKey];
358    context[validateDOMNesting.ancestorInfoContextKey] =
359      validateDOMNesting.updatedAncestorInfo(info, inst._tag, inst);
360  }
361  return context;
362}
363
364function isCustomComponent(tagName, props) {
365  return tagName.indexOf('-') >= 0 || props.is != null;
366}
367
368/**
369 * Creates a new React class that is idempotent and capable of containing other
370 * React components. It accepts event listeners and DOM properties that are
371 * valid according to `DOMProperty`.
372 *
373 *  - Event listeners: `onClick`, `onMouseDown`, etc.
374 *  - DOM properties: `className`, `name`, `title`, etc.
375 *
376 * The `style` property functions differently from the DOM API. It accepts an
377 * object mapping of style properties to values.
378 *
379 * @constructor ReactTVMLComponent
380 * @extends ReactMultiChild
381 */
382function ReactTVMLComponent(tag) {
383  validateDangerousTag(tag);
384  this._tag = tag.toLowerCase();
385  this._renderedChildren = null;
386  this._previousStyle = null;
387  this._previousStyleCopy = null;
388  this._rootNodeID = null;
389  this._wrapperState = null;
390  this._topLevelWrapper = null;
391  this._nodeWithLegacyProperties = null;
392}
393
394ReactTVMLComponent.displayName = 'ReactTVMLComponent';
395
396ReactTVMLComponent.Mixin = {
397
398  construct: function(element) {
399    this._currentElement = element;
400  },
401
402  /**
403   * Generates root tag markup then recurses. This method has side effects and
404   * is not idempotent.
405   *
406   * @internal
407   * @param {string} rootID The root DOM ID for this node.
408   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
409   * @param {object} context
410   * @return {string} The computed markup.
411   */
412  mountComponent: function(rootID, transaction, context) {
413    this._rootNodeID = rootID;
414
415    var props = this._currentElement.props;
416
417    if (hasOwnProperty(COMPONENT_CLASSES, this._tag)) {
418      if (hasOwnProperty(COMPONENT_CLASSES[this._tag], 'getNativeProps')) {
419        props = COMPONENT_CLASSES[this._tag].getNativeProps(this, props, context);
420      }
421    }
422
423    assertValidProps(this, props);
424    if (__DEV__) {
425      if (context[validateDOMNesting.ancestorInfoContextKey]) {
426        validateDOMNesting(
427          this._tag,
428          this,
429          context[validateDOMNesting.ancestorInfoContextKey]
430        );
431      }
432    }
433
434    var mountImage;
435    // isn't useCreateElement always false?
436    if (transaction.useCreateElement) {
437      var ownerDocument = context[Mount.ownerDocumentContextKey];
438      var el = ownerDocument.createElement(this._currentElement.type);
439      DOMPropertyOperations.setAttributeForID(el, this._rootNodeID);
440      // Populate node cache
441      Mount.getID(el);
442      this._updateDOMProperties({}, props, transaction, el);
443      this._createInitialChildren(transaction, props, context, el);
444      mountImage = el;
445    } else {
446      var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
447      var tagContent = this._createContentMarkup(transaction, props, context);
448      if (!tagContent && omittedCloseTags[this._tag]) {
449        mountImage = tagOpen + '/>';
450      } else {
451        mountImage =
452          tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
453      }
454    }
455
456    return mountImage;
457  },
458
459  /**
460   * Creates markup for the open tag and all attributes.
461   *
462   * This method has side effects because events get registered.
463   *
464   * Iterating over object properties is faster than iterating over arrays.
465   * @see http://jsperf.com/obj-vs-arr-iteration
466   *
467   * @private
468   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
469   * @param {object} props
470   * @return {string} Markup of opening tag.
471   */
472  _createOpenTagMarkupAndPutListeners: function(transaction, props) {
473    var ret = '<' + this._currentElement.type;
474
475    for (var propKey in props) {
476      if (!hasOwnProperty(props, propKey)) {
477        continue;
478      }
479      var propValue = props[propKey];
480      if (propValue == null) {
481        continue;
482      }
483      if (hasOwnProperty(EventEmitter.registrationNameModules, propKey)) {
484        enqueuePutListener(this._rootNodeID, propKey, propValue, transaction);
485      } else {
486        if (propKey === STYLE) {
487          if (propValue) {
488            if (__DEV__) {
489              // See `_updateDOMProperties`. style block
490              this._previousStyle = propValue;
491            }
492            propValue = this._previousStyleCopy = assign({}, props.style);
493          }
494          propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
495        }
496        var markup = null;
497        if (this._tag != null && isCustomComponent(this._tag, props)) {
498          markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
499        } else {
500          markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
501        }
502        if (markup) {
503          ret += ' ' + markup;
504        }
505      }
506    }
507
508    // For static pages, no need to put React ID and checksum. Saves lots of
509    // bytes.
510    if (transaction.renderToStaticMarkup) {
511      return ret;
512    }
513
514    var markupForID = DOMPropertyOperations.createMarkupForID(this._rootNodeID);
515    return ret + ' ' + markupForID;
516  },
517
518  /**
519   * Creates markup for the content between the tags.
520   *
521   * @private
522   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
523   * @param {object} props
524   * @param {object} context
525   * @return {string} Content markup.
526   */
527  _createContentMarkup: function(transaction, props, context) {
528    var ret = '';
529
530    // Intentional use of != to avoid catching zero/false.
531    var innerHTML = props.dangerouslySetInnerHTML;
532    if (innerHTML != null) {
533      if (innerHTML.__html != null) {
534        ret = innerHTML.__html;
535      }
536    } else {
537      var contentToUse =
538        CONTENT_TYPES[typeof props.children] ? props.children : null;
539      var childrenToUse = contentToUse != null ? null : props.children;
540      if (contentToUse != null) {
541        // TODO: Validate that text is allowed as a child of this node
542        ret = escapeTextContentForBrowser(contentToUse);
543      } else if (childrenToUse != null) {
544        var mountImages = this.mountChildren(
545          childrenToUse,
546          transaction,
547          processChildContext(context, this)
548        );
549        ret = mountImages.join('');
550      }
551    }
552    if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') {
553      // text/html ignores the first character in these tags if it's a newline
554      // Prefer to break application/xml over text/html (for now) by adding
555      // a newline specifically to get eaten by the parser. (Alternately for
556      // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
557      // \r is normalized out by HTMLTextAreaElement#value.)
558      // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
559      // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
560      // See: <http://www.w3.org/TR/html5/syntax.html#newlines>
561      // See: Parsing of "textarea" "listing" and "pre" elements
562      //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
563      return '\n' + ret;
564    } else {
565      return ret;
566    }
567  },
568
569  _createInitialChildren: function(transaction, props, context, el) {
570    // Intentional use of != to avoid catching zero/false.
571    var innerHTML = props.dangerouslySetInnerHTML;
572    if (innerHTML != null) {
573      if (innerHTML.__html != null) {
574        setInnerHTML(el, innerHTML.__html);
575      }
576    } else {
577      var contentToUse =
578        CONTENT_TYPES[typeof props.children] ? props.children : null;
579      var childrenToUse = contentToUse != null ? null : props.children;
580      if (contentToUse != null) {
581        // TODO: Validate that text is allowed as a child of this node
582        setTextContent(el, contentToUse);
583      } else if (childrenToUse != null) {
584        var mountImages = this.mountChildren(
585          childrenToUse,
586          transaction,
587          processChildContext(context, this)
588        );
589        for (var i = 0; i < mountImages.length; i++) {
590          el.appendChild(mountImages[i]);
591        }
592      }
593    }
594  },
595
596  /**
597   * Receives a next element and updates the component.
598   *
599   * @internal
600   * @param {ReactElement} nextElement
601   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
602   * @param {object} context
603   */
604  receiveComponent: function(nextElement, transaction, context) {
605    var prevElement = this._currentElement;
606    this._currentElement = nextElement;
607    this.updateComponent(transaction, prevElement, nextElement, context);
608  },
609
610  /**
611   * Updates a native DOM component after it has already been allocated and
612   * attached to the DOM. Reconciles the root DOM node, then recurses.
613   *
614   * @param {ReactReconcileTransaction} transaction
615   * @param {ReactElement} prevElement
616   * @param {ReactElement} nextElement
617   * @internal
618   * @overridable
619   */
620  updateComponent: function(transaction, prevElement, nextElement, context) {
621    var lastProps = prevElement.props;
622    var nextProps = this._currentElement.props;
623
624    if (hasOwnProperty(COMPONENT_CLASSES, this._tag)) {
625      if (hasOwnProperty(COMPONENT_CLASSES[this._tag], 'getNativeProps')) {
626        lastProps = COMPONENT_CLASSES[this._tag].getNativeProps(this, lastProps);
627        nextProps = COMPONENT_CLASSES[this._tag].getNativeProps(this, nextProps);
628      }
629    }
630
631    assertValidProps(this, nextProps);
632    this._updateDOMProperties(lastProps, nextProps, transaction, null);
633    this._updateDOMChildren(
634      lastProps,
635      nextProps,
636      transaction,
637      processChildContext(context, this)
638    );
639  },
640
641  /**
642   * Reconciles the properties by detecting differences in property values and
643   * updating the DOM as necessary. This function is probably the single most
644   * critical path for performance optimization.
645   *
646   * TODO: Benchmark whether checking for changed values in memory actually
647   *       improves performance (especially statically positioned elements).
648   * TODO: Benchmark the effects of putting this at the top since 99% of props
649   *       do not change for a given reconciliation.
650   * TODO: Benchmark areas that can be improved with caching.
651   *
652   * @private
653   * @param {object} lastProps
654   * @param {object} nextProps
655   * @param {ReactReconcileTransaction} transaction
656   * @param {?DOMElement} node
657   */
658  _updateDOMProperties: function(lastProps, nextProps, transaction, node) {
659    var propKey;
660    var styleName;
661    var styleUpdates;
662    for (propKey in lastProps) {
663      if (hasOwnProperty(nextProps, propKey) || !hasOwnProperty(lastProps, propKey)) {
664        continue;
665      }
666      if (propKey === STYLE) {
667        var lastStyle = this._previousStyleCopy;
668        for (styleName in lastStyle) {
669          if (hasOwnProperty(lastStyle, styleName)) {
670            styleUpdates = styleUpdates || {};
671            styleUpdates[styleName] = '';
672          }
673        }
674        this._previousStyleCopy = null;
675      } else if (hasOwnProperty(EventEmitter.registrationNameModules, propKey)) {
676        if (lastProps[propKey]) {
677          // Only call deleteListener if there was a listener previously or
678          // else willDeleteListener gets called when there wasn't actually a
679          // listener (e.g., onClick={null})
680          EventEmitter.deleteListener(this._rootNodeID, propKey);
681        }
682      } else if (
683          DOMProperty.properties[propKey] ||
684          DOMProperty.isCustomAttribute(propKey)) {
685        if (!node) {
686          node = Mount.getNode(this._rootNodeID);
687        }
688        DOMPropertyOperations.deleteValueForProperty(node, propKey);
689      }
690    }
691    for (propKey in nextProps) {
692      var nextProp = nextProps[propKey];
693      var lastProp = propKey === STYLE ?
694        this._previousStyleCopy :
695        lastProps[propKey];
696      if (!hasOwnProperty(nextProps, propKey) || nextProp === lastProp) {
697        continue;
698      }
699      if (propKey === STYLE) {
700        if (nextProp) {
701          if (__DEV__) {
702            checkAndWarnForMutatedStyle(
703              this._previousStyleCopy,
704              this._previousStyle,
705              this
706            );
707            this._previousStyle = nextProp;
708          }
709          nextProp = this._previousStyleCopy = assign({}, nextProp);
710        } else {
711          this._previousStyleCopy = null;
712        }
713        if (lastProp) {
714          // Unset styles on `lastProp` but not on `nextProp`.
715          for (styleName in lastProp) {
716            if (hasOwnProperty(lastProp, styleName) &&
717                (!nextProp || !hasOwnProperty(nextProp, styleName))) {
718              styleUpdates = styleUpdates || {};
719              styleUpdates[styleName] = '';
720            }
721          }
722          // Update styles that changed since `lastProp`.
723          for (styleName in nextProp) {
724            if (hasOwnProperty(nextProp, styleName) &&
725                lastProp[styleName] !== nextProp[styleName]) {
726              styleUpdates = styleUpdates || {};
727              styleUpdates[styleName] = nextProp[styleName];
728            }
729          }
730        } else {
731          // Relies on `updateStylesByID` not mutating `styleUpdates`.
732          styleUpdates = nextProp;
733        }
734      } else if (hasOwnProperty(propKey)) {
735        if (nextProp) {
736          enqueuePutListener(this._rootNodeID, propKey, nextProp, transaction);
737        } else if (lastProp) {
738          EventEmitter.deleteListener(this._rootNodeID, propKey);
739        }
740      } else if (isCustomComponent(this._tag, nextProps)) {
741        if (!node) {
742          node = Mount.getNode(this._rootNodeID);
743        }
744        DOMPropertyOperations.setValueForAttribute(
745          node,
746          propKey,
747          nextProp
748        );
749      } else if (
750          DOMProperty.properties[propKey] ||
751          DOMProperty.isCustomAttribute(propKey)) {
752        if (!node) {
753          node = Mount.getNode(this._rootNodeID);
754        }
755        // If we're updating to null or undefined, we should remove the property
756        // from the DOM node instead of inadvertantly setting to a string. This
757        // brings us in line with the same behavior we have on initial render.
758        if (nextProp != null) {
759          DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);
760        } else {
761          DOMPropertyOperations.deleteValueForProperty(node, propKey);
762        }
763      }
764    }
765    if (styleUpdates) {
766      if (!node) {
767        node = Mount.getNode(this._rootNodeID);
768      }
769      CSSPropertyOperations.setValueForStyles(node, styleUpdates);
770    }
771  },
772
773  /**
774   * Reconciles the children with the various properties that affect the
775   * children content.
776   *
777   * @param {object} lastProps
778   * @param {object} nextProps
779   * @param {ReactReconcileTransaction} transaction
780   * @param {object} context
781   */
782  _updateDOMChildren: function(lastProps, nextProps, transaction, context) {
783    var lastContent =
784      CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
785    var nextContent =
786      CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
787
788    var lastHtml =
789      lastProps.dangerouslySetInnerHTML &&
790      lastProps.dangerouslySetInnerHTML.__html;
791    var nextHtml =
792      nextProps.dangerouslySetInnerHTML &&
793      nextProps.dangerouslySetInnerHTML.__html;
794
795    // Note the use of `!=` which checks for null or undefined.
796    var lastChildren = lastContent != null ? null : lastProps.children;
797    var nextChildren = nextContent != null ? null : nextProps.children;
798
799    // If we're switching from children to content/html or vice versa, remove
800    // the old content
801    var lastHasContentOrHtml = lastContent != null || lastHtml != null;
802    var nextHasContentOrHtml = nextContent != null || nextHtml != null;
803    if (lastChildren != null && nextChildren == null) {
804      this.updateChildren(null, transaction, context);
805    } else if (lastHasContentOrHtml && !nextHasContentOrHtml) {
806      this.updateTextContent('');
807    }
808
809    if (nextContent != null) {
810      if (lastContent !== nextContent) {
811        this.updateTextContent('' + nextContent);
812      }
813    } else if (nextHtml != null) {
814      if (lastHtml !== nextHtml) {
815        this.updateMarkup('' + nextHtml);
816      }
817    } else if (nextChildren != null) {
818      this.updateChildren(nextChildren, transaction, context);
819    }
820  },
821
822  /**
823   * Destroys all event registrations for this instance. Does not remove from
824   * the DOM. That must be done by the parent.
825   *
826   * @internal
827   */
828  unmountComponent: function() {
829    this.unmountChildren();
830    EventEmitter.deleteAllListeners(this._rootNodeID);
831    IDOperations.unmountIDFromEnvironment(this._rootNodeID);
832    this._rootNodeID = null;
833    this._wrapperState = null;
834    if (this._nodeWithLegacyProperties) {
835      var node = this._nodeWithLegacyProperties;
836      node._reactInternalComponent = null;
837      this._nodeWithLegacyProperties = null;
838    }
839  },
840
841  getPublicInstance: function() {
842    if (this._nodeWithLegacyProperties) {
843      return this._nodeWithLegacyProperties;
844    }
845
846    var node = Mount.getNode(this._rootNodeID);
847
848    node._reactInternalComponent = this;
849    node.getDOMNode = legacyGetDOMNode;
850    node.isMounted = legacyIsMounted;
851    node.setState = legacySetStateEtc;
852    node.replaceState = legacySetStateEtc;
853    node.forceUpdate = legacySetStateEtc;
854    node.setProps = legacySetProps;
855    node.replaceProps = legacyReplaceProps;
856
857    // updateComponent will update this property on subsequent renders
858    node.props = this._currentElement.props;
859
860    this._nodeWithLegacyProperties = node;
861  }
862};
863
864Perf.measureMethods(ReactTVMLComponent, 'ReactTVMLComponent', {
865  mountComponent: 'mountComponent',
866  updateComponent: 'updateComponent'
867});
868
869assign(
870  ReactTVMLComponent.prototype,
871  ReactTVMLComponent.Mixin,
872  MultiChild.Mixin
873);
874
875module.exports = ReactTVMLComponent;
876
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Playwright Internal on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)