Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CPLAT-2272: Add UiComponent2 (JS-backed maps) #271

Merged
merged 43 commits into from
Mar 20, 2019

Conversation

greglittlefield-wf
Copy link
Contributor

@greglittlefield-wf greglittlefield-wf commented Mar 14, 2019

Ultimate problem:

Add over_react analogues of Component2, introduced in react-dart to implement JS-object-based props/state and to serve as the basis for React 16 lifecycle methods.

See Workiva/react-dart#161 for more context

Changes

  • Initial implementation of JS-object-based props/state of UiComponent2/UiStatefulComponent2` base classes
    • This API is extremely far from final; it currently contains pieces that will be removed or completely reworked before release
  • Update props/state typing mechanism in component classes
    • Generate an additional UiProps class implementation for each component that can only be backed by JS maps, and override the return type of typedPropsFactoryJs/props to match this.
      This allows dart2js to make some optimizations. For instance:

      For the access of props.isOpen within a component, as we start to inline things (for the purposes of understanding what's going on under the hood), then it looks like this:

      props.isOpen;
      props.props['isOpen'];             // inline FooProps.isOpen typed getter
      props.props.backingMap['isOpen'];  // inline UiProps.operator[]

      So, we're eventually accessing a property on the Map backingMap.

      But if backingMap is a JsBackedMap, we can go one layer deeper:

      props.props.backingMap['isOpen'];
      getProperty(props.props.backingMap.jsMap, 'isOpen'); // inline JsBackedMap.operator[]

      Now, onto dart2js, which performs actual inlining in certain cases (like prop accesses).

      When dart2js only knows that backingMap is a Map, it emits the following code, wherein
      $index$asx performs type-checking on the map and key, and then performs an interceptor lookup on the backing map before finally calling into the actual key lookup function.

      J.$index$asx(this._cachedTypedProps.props.backingMap, 'isOpen');

      However, when dart2js knows that backingMap is a JsMap, it can skip that step and emit
      code that directly accesses the JS property

      this._cachedTypedProps.props.backingMap.jsMap.isOpen;
  • Add integration tests for UiComponent2 to serve as a smoke branch as we finalize this work.
    • Remove deprecated @Required annotation that was being tested, as well as related tests
  • Update components in web/ to use Ui(Stateful)Component2
  • Update boilerplate with new link to dart-lang/sdk issue
  • Add ignores for deprecation warnings introduced by react-dart 5.0.0-wip
  • Duplicate examples in web/ with UiComponent2 versions

Testing

  • CI passes
  • Play around with web/component2/ examples and verify their props/state show up in the dev tools as expected!

Potential areas of regression:

  • Builder

FYA: @aaronlademann-wf @kealjones-wk
FYI: @evanweible-wf @corwinsheahan-wf @maxwellpeterson-wf

@greglittlefield-wf greglittlefield-wf requested a review from a team as a code owner March 14, 2019 23:40
@aviary2-wf
Copy link

Security Insights

No security relevant content was detected by automated scans.

Action Items

  • Review PR for security impact; comment "security review required" if needed or unsure
  • Verify aviary.yaml coverage of security relevant code

Questions or Comments? Reach out on Slack: #support-infosec.

@greglittlefield-wf greglittlefield-wf changed the title Js map perf/dart2 CPLAT-2272: Add UiComponent2 (JS-backed maps) Mar 14, 2019
Copy link
Contributor

@aaronlademann-wf aaronlademann-wf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably go ahead and deprecate all the old component classes.

..writeln(' // of `_$propsOrState` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217')
// TODO need to remove this workaround once https://github.com/dart-lang/sdk/issues/36217 is fixed get nice dart2js output
..writeln(' $plainMapImplName(Map backingMap) : this._$propsOrState = {}, super._() {')
..writeln(' this._$propsOrState = backingMap ?? {};')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any benefit to making the fallback be const {}?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't because this map backs the returned props object, which can be mutated.

lib/src/component_declaration/component_base.dart Outdated Show resolved Hide resolved
lib/src/component_declaration/builder_helpers.dart Outdated Show resolved Hide resolved
lib/src/component_declaration/component_base.dart Outdated Show resolved Hide resolved
lib/src/component_declaration/component_base.dart Outdated Show resolved Hide resolved
lib/src/component_declaration/component_base.dart Outdated Show resolved Hide resolved
pubspec.yaml Outdated Show resolved Hide resolved
web/src/demo_components/button.dart Outdated Show resolved Hide resolved
Copy link
Contributor

@aaronlademann-wf aaronlademann-wf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@@ -27,7 +27,7 @@ export 'package:react/react.dart' show
SyntheticUIEvent,
SyntheticWheelEvent;

// FIXME use public entrypoint
// FIXME 3.0.0-wip use public entrypoint
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -31,6 +30,9 @@ import 'package:w_common/disposable.dart';

export 'package:over_react/src/component_declaration/component_type_checking.dart' show isComponentOfType, isValidElementOfType;

part 'component_base/component_base_2.dart';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

Copy link
Contributor

@aaronlademann-wf aaronlademann-wf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA +1

@Workiva/release-management-pp

@rmconsole6-wk rmconsole6-wk merged commit e08f05d into 3.0.0-wip Mar 20, 2019
@rmconsole6-wk rmconsole6-wk deleted the js_map_perf/dart2 branch March 20, 2019 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants