Nifty SHAs of Code

a day in the life of a bug

Pete Bacon Darwin

Kitalogue

Angular 1.4.0 is out!

Woohoo - let's upgrade

Angular Broke

My App!

Ye Olde Days

(Closed Source proprietary API)

Open Source

to the rescue!

(Comic by Nina Paley / CC By-SA 3.0)

Angular loves Open Source

In the five years that Angular.js has been around:

  • more than 1200 contributors

    • almost 400 providing significant code
  • ~5500 issues and ~5500 PRs handled
  • almost 7000 commits merged

By Nevit Dilmen (Own work) [CC BY-SA 3.0]

DISCLAIMER

AngularJS is not the only Open Source project in the Universe

Report the bug

Bad! This is not actionable

There is a better way...

Six Golden Steps

  1. Analyse the bug

  2. Post an issue

  3. Fix the problem

  4. Submit the fix

  5. Deal with feedback

  6. Bask in the glory of being a super hero contributor

1 Analyse the bug

  • What are the symptoms?
  • What is the environment?
    • Version of Angular
    • Make and version of browser
    • 3rd party libraries
  • Are there error messages?
  • Steps to reproduce the bug
  • Overlooked breaking change?

2 Post an Issue

  • Search for known issues on Github
  • Identify the crux of the problem
  • Create an issue on Github
  • Bonus Points:
    • Create a minimal runnable demo
    • Create a failing unit test
    • Suggest a solution

Awesome Example

ngOptions incorrectly evaluates label for $$hashKey when watching labels

https://github.com/angular/angular.js/issues/11930

Other Good Examples

1.3.x ngCookies service overwrites/duplicates cookies set outside of ngCookies

https://github.com/angular/angular.js/issues/11490

 

AngularJS is throwing "TypeError: Cannot read property 'childNodes' of undefined" when using DOM elements that trigger directives in ng-view

https://github.com/angular/angular.js/issues/5069

Go the extra mile...

3 Fix the Problem

  • Fork repo on Github
  • Set up development environment
  • Write a failing test
  • Identify a solution that passes the checks and tests
  • Update docs if necessary

Fork the repository

Setup your Dev Environment

  • git clone https://github.com/USERNAME/angular.js
    
  • npm install
  • npm install -g grunt
  • git checkout -b select-label-watch-bug v1.4.0
    
  • grunt package
  • grunt autotest

Write a failing test

it('should not watch array properties that start with $ or $$', function() {
  createSelect({
    'ng-options': 'value as createLabel(value) for value in array',
    'ng-model': 'selected'
  });
  scope.createLabel = jasmine.createSpy()
                        .andCallFake(function(value) { return value; });
  scope.array = ['a', 'b', 'c'];
  scope.array.$$private = 'do not watch';
  scope.array.$property = 'do not watch';
  scope.selected = 'b';
  scope.$digest();

  expect(scope.createLabel).toHaveBeenCalledWith('a');
  expect(scope.createLabel).toHaveBeenCalledWith('b');
  expect(scope.createLabel).toHaveBeenCalledWith('c');
  expect(scope.createLabel).not.toHaveBeenCalledWith('do not watch');
});

 

Find a solution

Object.keys(values).forEach(function getWatchable(key) {
  
  if (key.charAt(0) === '$') return;

  var locals = getLocals(values[key], key);
  var selectValue = getTrackByValueFn(values[key], locals);
  watchedArray.push(selectValue);

  // Only need to watch the displayFn if there is a specific label expression
  if (match[2] || match[1]) {
    var label = displayFn(scope, locals);
    watchedArray.push(label);
  }

  // Only need to watch the disableWhenFn if there is a specific disable expression
  if (match[4]) {
    var disableWhen = disableWhenFn(scope, locals);
    watchedArray.push(disableWhen);
  }
});

 

Check it in your app

  • grunt build
    
  • cp build/angular.js myApp

Sanity Check

  grunt test

 

This is equivalent to

  grunt jshint
  grunt jscs
  grunt package
  grunt test:unit
  grunt test:promises-aplus
  grunt tests:docs
  grunt test:protractor

Submit the fix

Commit Messages

Commit Message Conventions

fix(ngOptions): do not watch properties starting with $

Expressions that compute labels and track by values for ngOptions were being called for properties, that start with $ even though those properties were being ignored as options.

Closes #11930

Get Feedback

  • Deal with comments and suggestions

  • Add new commits (no need to squash or force push)

Enjoy the merge!

  • Sit back and bask in contribution glory

  • Bonus Points:

    • Watch for related regressions appearing in issues

Thanks

Nifty SHAs of Code

By Pete Bacon Darwin

Nifty SHAs of Code

  • 2,517