perf(*): Replace _.omit, refresh scrollbar height less often

This commit is contained in:
Ben Gotow 2016-03-24 13:55:26 -07:00
parent 4bfb4fe916
commit fc33e97bf8
21 changed files with 39 additions and 32 deletions

View file

@ -1,12 +1,12 @@
React = require 'react' React = require 'react'
_ = require 'underscore' {Utils} = require 'nylas-exports'
class SendingProgressBar extends React.Component class SendingProgressBar extends React.Component
@propTypes: @propTypes:
progress: React.PropTypes.number.isRequired progress: React.PropTypes.number.isRequired
render: -> render: ->
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = Utils.fastOmit(@props, Object.keys(@constructor.propTypes))
if 0 < @props.progress < 99 if 0 < @props.progress < 99
<div className="sending-progress" {...otherProps}> <div className="sending-progress" {...otherProps}>
<div className="filled" <div className="filled"

View file

@ -10,7 +10,7 @@ class DropZone extends React.Component
constructor: -> constructor: ->
render: -> render: ->
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = _.omit(@props, Object.keys(@constructor.propTypes))
<div {...otherProps} onDragEnter={@_onDragEnter} onDragLeave={@_onDragLeave} onDrop={@_onDrop}> <div {...otherProps} onDragEnter={@_onDragEnter} onDragLeave={@_onDragLeave} onDrop={@_onDrop}>
{@props.children} {@props.children}
</div> </div>

View file

@ -168,7 +168,7 @@ class FixedPopover extends Component {
computeAdjustedOffsetAndDirection = ({direction, currentRect, windowDimensions, fallback = this.fallback, offsetPadding = OFFSET_PADDING})=> { computeAdjustedOffsetAndDirection = ({direction, currentRect, windowDimensions, fallback = this.fallback, offsetPadding = OFFSET_PADDING})=> {
const {overflows, overflowValues} = this.computeOverflows({currentRect, windowDimensions}) const {overflows, overflowValues} = this.computeOverflows({currentRect, windowDimensions})
const overflowCount = _.keys(_.pick(overflows, (val)=> val === true)).length const overflowCount = Object.keys(_.pick(overflows, (val)=> val === true)).length
if (overflowCount > 0) { if (overflowCount > 0) {
if (fallback) { if (fallback) {

View file

@ -1,6 +1,6 @@
React = require 'react' React = require 'react'
_ = require 'underscore' _ = require 'underscore'
{Actions,ComponentRegistry} = require "nylas-exports" {Actions, ComponentRegistry, Utils} = require "nylas-exports"
### ###
Public: A simple wrapper that provides a Flexbox layout with the given direction and style. Public: A simple wrapper that provides a Flexbox layout with the given direction and style.
@ -36,8 +36,7 @@ class Flexbox extends React.Component
if @props.inline is true if @props.inline is true
style.display = 'inline-flex' style.display = 'inline-flex'
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = Utils.fastOmit(@props, Object.keys(@constructor.propTypes))
<div style={style} {...otherProps}> <div style={style} {...otherProps}>
{@props.children} {@props.children}
</div> </div>

View file

@ -29,7 +29,7 @@ class FluxContainer extends React.Component
@_unlisteners = [] @_unlisteners = []
render: -> render: ->
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = _.omit(@props, Object.keys(@constructor.propTypes))
React.cloneElement(@props.children, _.extend({}, otherProps, @state)) React.cloneElement(@props.children, _.extend({}, otherProps, @state))
module.exports = FluxContainer module.exports = FluxContainer

View file

@ -3,7 +3,8 @@ _ = require 'underscore'
UnsafeComponent = require './unsafe-component' UnsafeComponent = require './unsafe-component'
Flexbox = require './flexbox' Flexbox = require './flexbox'
InjectedComponentLabel = require './injected-component-label' InjectedComponentLabel = require './injected-component-label'
{Actions, {Utils,
Actions,
WorkspaceStore, WorkspaceStore,
ComponentRegistry} = require "nylas-exports" ComponentRegistry} = require "nylas-exports"
@ -89,7 +90,7 @@ class InjectedComponentSet extends React.Component
render: => render: =>
@_renderedComponents = new Set() @_renderedComponents = new Set()
flexboxProps = _.omit(@props, _.keys(@constructor.propTypes)) flexboxProps = Utils.fastOmit(@props, Object.keys(@constructor.propTypes))
flexboxClassName = @props.className ? "" flexboxClassName = @props.className ? ""
exposedProps = @props.exposedProps ? {} exposedProps = @props.exposedProps ? {}

View file

@ -182,7 +182,7 @@ class KeyCommandsRegion extends React.Component
classname = classNames classname = classNames
'key-commands-region': true 'key-commands-region': true
'focused': @state.focused 'focused': @state.focused
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = _.omit(@props, Object.keys(@constructor.propTypes))
<div className="#{classname} #{@props.className}" {...otherProps}> <div className="#{classname} #{@props.className}" {...otherProps}>
{@props.children} {@props.children}

View file

@ -21,13 +21,13 @@ class ListTabularItem extends React.Component
if not Utils.isEqualReact(@props.item, nextProps.item) or @props.columns isnt nextProps.columns if not Utils.isEqualReact(@props.item, nextProps.item) or @props.columns isnt nextProps.columns
@_columnCache = null @_columnCache = null
return true return true
if not Utils.isEqualReact(_.omit(@props, 'item'), _.omit(nextProps, 'item')) if not Utils.isEqualReact(Utils.fastOmit(@props, ['item']), Utils.fastOmit(nextProps, ['item']))
return true return true
false false
render: => render: =>
className = "list-item list-tabular-item #{@props.itemProps?.className}" className = "list-item list-tabular-item #{@props.itemProps?.className}"
props = _.omit(@props.itemProps ? {}, 'className') props = Utils.fastOmit(@props.itemProps ? {}, ['className'])
# It's expensive to compute the contents of columns (format timestamps, etc.) # It's expensive to compute the contents of columns (format timestamps, etc.)
# We only do it if the item prop has changed. # We only do it if the item prop has changed.
@ -48,7 +48,7 @@ class ListTabularItem extends React.Component
<div key={column.name} <div key={column.name}
displayName={column.name} displayName={column.name}
style={_.pick(column, ['flex', 'width'])} style={{flex: column.flex, width: column.width}}
className="list-column list-column-#{column.name}"> className="list-column list-column-#{column.name}">
{column.resolver(@props.item, @)} {column.resolver(@props.item, @)}
</div> </div>

View file

@ -157,7 +157,7 @@ class ListTabular extends React.Component
@setState(@buildStateForRange(start: rangeStart, end: rangeEnd)) @setState(@buildStateForRange(start: rangeStart, end: rangeEnd))
render: => render: =>
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = Utils.fastOmit(@props, Object.keys(@constructor.propTypes))
innerStyles = innerStyles =
height: @state.count * @props.itemHeight height: @state.count * @props.itemHeight

View file

@ -89,7 +89,7 @@ class MultiselectList extends React.Component
# BAD: onSelect={ (item) -> Actions.focusThread(item) } # BAD: onSelect={ (item) -> Actions.focusThread(item) }
# GOOD: onSelect={@_onSelectItem} # GOOD: onSelect={@_onSelectItem}
# #
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = Utils.fastOmit(@props, Object.keys(@constructor.propTypes))
className = @props.className className = @props.className
if @props.dataSource and @state.handler if @props.dataSource and @state.handler

View file

@ -1,6 +1,7 @@
React = require 'react' React = require 'react'
_ = require 'underscore' _ = require 'underscore'
{Actions, {Utils,
Actions,
ComponentRegistry, ComponentRegistry,
PriorityUICoordinator} = require "nylas-exports" PriorityUICoordinator} = require "nylas-exports"
@ -93,7 +94,7 @@ class ResizableRegion extends React.Component
else else
containerStyle.flex = 1 containerStyle.flex = 1
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = Utils.fastOmit(@props, Object.keys(@constructor.propTypes))
<div style={containerStyle} {...otherProps}> <div style={containerStyle} {...otherProps}>
{@props.children} {@props.children}

View file

@ -121,7 +121,7 @@ class RetinaImg extends React.Component
if key in StylesImpactedByZoom and val.indexOf('%') is -1 if key in StylesImpactedByZoom and val.indexOf('%') is -1
style[key] = val.replace('px','') / style.zoom style[key] = val.replace('px','') / style.zoom
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = Utils.fastOmit(@props, Object.keys(@constructor.propTypes))
<img className={className} src={path} style={style} {...otherProps} /> <img className={className} src={path} style={style} {...otherProps} />
_pathFor: (name) => _pathFor: (name) =>

View file

@ -199,7 +199,7 @@ class ScrollRegion extends React.Component
}) })
componentDidUpdate: (prevProps, prevState) => componentDidUpdate: (prevProps, prevState) =>
if (@props.children != prevProps.children) if not @state.scrolling and @props.children isnt prevProps.children
@recomputeDimensions() @recomputeDimensions()
componentWillReceiveProps: (props) => componentWillReceiveProps: (props) =>
@ -234,7 +234,7 @@ class ScrollRegion extends React.Component
scrollTooltipComponent={@props.scrollTooltipComponent} scrollTooltipComponent={@props.scrollTooltipComponent}
getScrollRegion={@_getSelf} /> getScrollRegion={@_getSelf} />
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = Utils.fastOmit(@props, Object.keys(@constructor.propTypes))
<div className={containerClasses} {...otherProps}> <div className={containerClasses} {...otherProps}>
{@_scrollbarComponent} {@_scrollbarComponent}
@ -379,6 +379,7 @@ class ScrollRegion extends React.Component
@_onScrollEnd ?= _.debounce => @_onScrollEnd ?= _.debounce =>
@_setSharedState(scrolling: false) @_setSharedState(scrolling: false)
@recomputeDimensions()
@props.onScrollEnd?(event) @props.onScrollEnd?(event)
, 250 , 250
@_onScrollEnd() @_onScrollEnd()

View file

@ -103,7 +103,7 @@ class Spinner extends React.Component
'zIndex': @props.zIndex+1 ? 1001 'zIndex': @props.zIndex+1 ? 1001
'transform':'translate(-50%,-50%)' 'transform':'translate(-50%,-50%)'
otherProps = _.omit(@props, _.keys(@constructor.propTypes)) otherProps = _.omit(@props, Object.keys(@constructor.propTypes))
<div className={spinnerClass} {...otherProps} style={style}> <div className={spinnerClass} {...otherProps} style={style}>
<div className="bounce1"></div> <div className="bounce1"></div>

View file

@ -1,6 +1,7 @@
import React, {Component, PropTypes} from 'react'; import React, {Component, PropTypes} from 'react';
import _ from 'underscore'; import _ from 'underscore';
import {exec} from 'child_process'; import {exec} from 'child_process';
import {Utils} from 'nylas-exports';
// This is a stripped down version of // This is a stripped down version of
// https://github.com/michaelvillar/dynamics.js/blob/master/src/dynamics.coffee#L1179, // https://github.com/michaelvillar/dynamics.js/blob/master/src/dynamics.coffee#L1179,
@ -309,8 +310,7 @@ export default class SwipeContainer extends Component {
render() { render() {
const {currentX, targetX} = this.state; const {currentX, targetX} = this.state;
const otherProps = _.omit(this.props, _.keys(this.constructor.propTypes)); const otherProps = Utils.fastOmit(this.props, Object.keys(this.constructor.propTypes));
const backingStyles = {top: 0, bottom: 0, position: 'absolute'}; const backingStyles = {top: 0, bottom: 0, position: 'absolute'};
let backingClass = 'swipe-backing'; let backingClass = 'swipe-backing';

View file

@ -60,7 +60,7 @@ class UnsafeComponent extends React.Component
node = React.findDOMNode(@) node = React.findDOMNode(@)
element = null element = null
try try
props = _.omit(@props, _.keys(@constructor.propTypes)) props = Utils.fastOmit(@props, Object.keys(@constructor.propTypes))
component = @props.component component = @props.component
element = <component key={name} {...props} /> element = <component key={name} {...props} />
@injected = React.render(element, node, @props.onComponentDidRender) @injected = React.render(element, node, @props.onComponentDidRender)

View file

@ -40,7 +40,7 @@ export function adaptContenteditableMethod(extension, method, original = extensi
extension[method] = (argsObj)=> { extension[method] = (argsObj)=> {
const {editor, event, mutations} = argsObj; const {editor, event, mutations} = argsObj;
const eventOrMutations = event || mutations || {}; const eventOrMutations = event || mutations || {};
const extraArgs = _.keys(_.omit(argsObj, ['editor', 'event', 'mutations'])).map( const extraArgs = Object.keys(_.omit(argsObj, ['editor', 'event', 'mutations'])).map(
key => argsObj[key] key => argsObj[key]
); );

View file

@ -194,7 +194,7 @@ export default class QuerySubscription {
_getMissingRange = (desiredRange, currentRange) => { _getMissingRange = (desiredRange, currentRange) => {
if (currentRange && !currentRange.isInfinite() && !desiredRange.isInfinite()) { if (currentRange && !currentRange.isInfinite() && !desiredRange.isInfinite()) {
const ranges = QueryRange.rangesBySubtracting(desiredRange, currentRange); const ranges = QueryRange.rangesBySubtracting(desiredRange, currentRange);
return ranges.length > 1 ? desiredRange : ranges[0]; return (ranges.length === 1) ? ranges[0] : desiredRange;
} }
return desiredRange; return desiredRange;
} }

View file

@ -51,6 +51,11 @@ Utils =
fullTimeString: (time) -> fullTimeString: (time) ->
moment(time).tz(Utils.timeZone).format("dddd, MMMM Do YYYY, h:mm:ss a z") moment(time).tz(Utils.timeZone).format("dddd, MMMM Do YYYY, h:mm:ss a z")
fastOmit: (props, without) ->
otherProps = Object.assign({}, props)
delete otherProps[w] for w in without
otherProps
isHash: (object) -> isHash: (object) ->
_.isObject(object) and not _.isFunction(object) and not _.isArray(object) _.isObject(object) and not _.isFunction(object) and not _.isArray(object)
@ -335,11 +340,11 @@ Utils =
else else
# Deep compare objects. # Deep compare objects.
key = undefined key = undefined
keys = _.keys(a) keys = Object.keys(a)
length = keys.length length = keys.length
# Ensure that both objects contain the same number of properties # Ensure that both objects contain the same number of properties
# before comparing deep equality. # before comparing deep equality.
if (_.keys(b).length isnt length) then return false if (Object.keys(b).length isnt length) then return false
keysToIgnore = {} keysToIgnore = {}
if options.ignoreKeys and _.isArray(options.ignoreKeys) if options.ignoreKeys and _.isArray(options.ignoreKeys)
keysToIgnore[key] = true for key in options.ignoreKeys keysToIgnore[key] = true for key in options.ignoreKeys

View file

@ -474,7 +474,7 @@ class PackageManager
null null
unloadPackages: -> unloadPackages: ->
@unloadPackage(name) for name in _.keys(@loadedPackages) @unloadPackage(name) for name in Object.keys(@loadedPackages)
null null
unloadPackage: (name) -> unloadPackage: (name) ->

View file

@ -425,7 +425,7 @@ class Package
if @bundledPackage and packagesCache[@name]? if @bundledPackage and packagesCache[@name]?
if packagesCache[@name].main if packagesCache[@name].main
@mainModulePath = "#{NylasEnv.packages.resourcePath}#{path.sep}#{packagesCache[@name].main}" @mainModulePath = "#{NylasEnv.packages.resourcePath}#{path.sep}#{packagesCache[@name].main}"
@mainModulePath = fs.resolveExtension(@mainModulePath, ["", _.keys(require.extensions)...]) @mainModulePath = fs.resolveExtension(@mainModulePath, ["", Object.keys(require.extensions)...])
else else
@mainModulePath = null @mainModulePath = null
else else
@ -434,7 +434,7 @@ class Package
path.join(@path, @metadata.main) path.join(@path, @metadata.main)
else else
path.join(@path, 'index') path.join(@path, 'index')
@mainModulePath = fs.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...]) @mainModulePath = fs.resolveExtension(mainModulePath, ["", Object.keys(require.extensions)...])
hasActivationCommands: -> hasActivationCommands: ->
for selector, commands of @getActivationCommands() for selector, commands of @getActivationCommands()