Eric Lewis ericandrewlewis Software Engineer @google New York, NY http://www.ericandrewlewis.com

issue openedlydell/source-map-visualize

spawn E2BIG error

Hi, thanks for building this! I'm excited to use it.

I get an error when I attempt to run it against a medium large sized project:

$ ./source-map-visualize ../v0.js.br
internal/child_process.js:366
    throw errnoException(err, 'spawn');
    ^

Error: spawn E2BIG
    at ChildProcess.spawn (internal/child_process.js:366:11)
    at Object.spawn (child_process.js:538:9)
    at Object.module.exports [as open] (/usr/local/google/home/ericnyc/Desktop/source-map-visualize/node_modules/opn/index.js:75:24)
    at /usr/local/google/home/ericnyc/Desktop/source-map-visualize/cli.js:100:11
    at /usr/local/google/home/ericnyc/Desktop/source-map-visualize/index.js:40:9
    at /usr/local/google/home/ericnyc/Desktop/source-map-visualize/node_modules/source-map-resolve/lib/source-map-resolve-node.js:263:7
    at done (/usr/local/google/home/ericnyc/Desktop/source-map-visualize/node_modules/source-map-resolve/lib/source-map-resolve-node.js:137:7)
    at ReadFileContext.callback (/usr/local/google/home/ericnyc/Desktop/source-map-visualize/node_modules/source-map-resolve/lib/source-map-resolve-node.js:150:9)
    at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:238:13)

Googling around tells me that this has to do with the size of the arguments passed to a child process, so I should note that my ARG_MAX is set to 2097152.

created time in 15 days

PR opened slightlyoff/never_slow_mode

Typo fix
+1 -1

0 comment

1 changed file

pr created time in 23 days

push eventericandrewlewis/never_slow_mode

Eric Lewis

commit sha 764bb80371bf69f204e0321ddc684b32ca85dab3

Typo fix

view details

push time in 23 days

fork ericandrewlewis/never_slow_mode

Never-Slow Mode (a.k.a. Slightly-Fast Mode)

fork in 23 days

GollumEvent
GollumEvent

pull request commentampproject/amphtml

🐛✅Fix tickevent tests for Safari

Lint fixed @lannka

ericandrewlewis

comment created time in a month

push eventericandrewlewis/amphtml

Eric Lewis

commit sha e517fa3a59377521a3e1de6b64e4c83fec55c435

Fix lint

view details

push time in a month

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 describes.realWin('PeformanceObserver metrics', {amp: true}, env => {       env.win.perfMetrics = previousPerfMetrics;     }   });++  describe('forwards layout jank metric', () => {+    it('for browsers that support the visibilitychange event', () => {+      // Fake the window object so we can control the state+      // of window.document.visibilityState later on.+      const fakeWin = {+        Date: env.win.Date,+        PerformanceLayoutJank: true,+        PerformanceObserver: env.sandbox.stub(),+        addEventListener: env.sandbox.stub(),+        dispatchEvent: env.win.dispatchEvent,+        document: {+          addEventListener: env.sandbox.stub(),+          hidden: false,+          readyState: 'complete',+          removeEventListener: env.sandbox.stub(),+          // Note: the document starts in a visible state.+          visibilityState: 'visible',+        },+        location: env.win.location,+        navigator: {+          // Note: specify an Android Chrome user agent, which supports+          // the visibilitychange event.+          userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL ' ++          'Build/OPR6.170623.011) AppleWebKit/537.36 (KHTML, like Gecko) ' ++          'Chrome/61.0.3163.98 Mobile Safari/537.36',+        },+        performance: {+          getEntriesByType: env.sandbox.stub(),+        },+        removeEventListener: env.win.removeEventListener,+      };

I should say, done in a fashion I figured out. Does the stubbing make sense?

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 describes.realWin('PeformanceObserver metrics', {amp: true}, env => {       env.win.perfMetrics = previousPerfMetrics;     }   });++  describe('forwards layout jank metric', () => {+    it('for browsers that support the visibilitychange event', () => {+      // Fake the window object so we can control the state+      // of window.document.visibilityState later on.+      const fakeWin = {+        Date: env.win.Date,+        PerformanceLayoutJank: true,+        PerformanceObserver: env.sandbox.stub(),+        addEventListener: env.sandbox.stub(),+        dispatchEvent: env.win.dispatchEvent,+        document: {+          addEventListener: env.sandbox.stub(),+          hidden: false,+          readyState: 'complete',+          removeEventListener: env.sandbox.stub(),+          // Note: the document starts in a visible state.+          visibilityState: 'visible',+        },+        location: env.win.location,+        navigator: {+          // Note: specify an Android Chrome user agent, which supports+          // the visibilitychange event.+          userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL ' ++          'Build/OPR6.170623.011) AppleWebKit/537.36 (KHTML, like Gecko) ' ++          'Chrome/61.0.3163.98 Mobile Safari/537.36',+        },+        performance: {+          getEntriesByType: env.sandbox.stub(),+        },+        removeEventListener: env.win.removeEventListener,+      };

Done in 3dd44e1

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     /** @private {number|null} */     this.firstViewportReady_ = null; +    /**+     * Whether the `lj` metric was ticked.+     *+     * @private {boolean}+     */+    this.tickedFirstJankScore_ = false;++    /**+     * Whether the `lj-2` metric was ticked.+     *+     * @private {boolean}+     */+    this.tickedSecondJankScore_ = false;++    /**+     * The sum of all layout jank fractions triggered on the page from the+     * Layout Jank API.+     *+     * @private {number}+     */+    this.aggregateJankScore_ = 0;++    this.onVisibilityChange_ = this.onVisibilityChange_.bind(this);+    this.tickLayoutJankScore_ = this.tickLayoutJankScore_.bind(this);

Done in 3dd44e1

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     /** @private {number|null} */     this.firstViewportReady_ = null; +    /**+     * Whether the `lj` metric was ticked.+     *+     * @private {boolean}+     */+    this.tickedFirstJankScore_ = false;++    /**+     * Whether the `lj-2` metric was ticked.+     *+     * @private {boolean}+     */+    this.tickedSecondJankScore_ = false;

Done in 3dd44e1

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     });   } +  /**+   * When the visibility state of the document changes to hidden,+   * send the layout jank score.+   */+  onVisibilityChange_() {+    if (this.win.document.visibilityState !== 'hidden') {

Done in 3dd44e1

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     });   } +  /**+   * When the visibility state of the document changes to hidden,+   * send the layout jank score.+   */+  onVisibilityChange_() {+    if (this.win.document.visibilityState !== 'hidden') {+      return;+    }+    this.tickLayoutJankScore_();+  }++  /**+   * Tick the layout jank score metric.+   *+   * A value of the metric is recorded in under two names, `lj` and `lj-2`,+   * for the first two times the page transitions into a hidden lifecycle state+   * (when the page is navigated a way from, the tab is backgrounded for+   * another tab, or the user backgrounds the browser application).+   *+   * Since we can't reliably detect when a page session finally ends,+   * recording the value for these first two events should provide a fair+   * amount of visibility into this metric.+   */+  tickLayoutJankScore_() {+    if (!this.tickedFirstJankScore_) {+      this.tickDelta('lj', this.aggregateJankScore_);+      this.flush();+      this.tickedFirstJankScore_ = true;+      return;+    }+    if (!this.tickedSecondJankScore_) {+      this.tickDelta('lj-2', this.aggregateJankScore_);+      this.flush();+      this.tickedSecondJankScore_ = true;++      const platform = Services.platformFor(this.win);+      if (platform.isSafari()) {+        this.win.removeEventListener('beforeunload', this.tickLayoutJankScore_);+      }+    }

Done in 3dd44e1

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 3dd44e1d3cae9badf3faac4d016ec85276bda1e4

Prefer stubbing in tests, other small fixes

view details

push time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {       entryTypesToObserve.push('firstInput');     } +    if (this.win.PerformanceLayoutJank) {+      // Programmatically read once as currently PerformanceObserver does not+      // report past entries as of Chrome 61.+      // https://bugs.chromium.org/p/chromium/issues/detail?id=725567+      this.win.performance.getEntriesByType('layoutJank').forEach(processEntry);+      entryTypesToObserve.push('layoutJank');++      // Register a handler to record the layout jank metric when the page+      // enters the hidden lifecycle state.+      // @see https://developers.google.com/web/updates/2018/07/page-lifecycle-api+      this.win.addEventListener(+          'visibilitychange',+          this.onVisibilityChange_,+          {capture: true}+      );

Based on notes about capture usage in the Page Lifecycle API docs we should be able to use a common listener in the bubble phase rather than capture.

Done in 363f278

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 363f27815339685ab6f2cddd9952eb12b884d545

Prefer DocumentState service to custom event listening

view details

push time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 function incOrDef(obj, name) {   } } +/**+ * Confirm whether the provided userAgent represents a Safari browser.+ *+ * @param {string} userAgent+ */+export function isSafari(userAgent) {+  const isEdge = /Edge/i.test(userAgent);+  const isOpera = /OPR\/|Opera|OPiOS/i.test(userAgent);+  const isChrome = /Chrome|CriOS/i.test(userAgent) && !isEdge && !isOpera;+  const isFirefox = /Firefox|FxiOS/i.test(userAgent) && !isEdge;+  const isIe = /Trident|MSIE|IEMobile/i.test(userAgent);+  return /Safari/i.test(userAgent) && !isChrome && !isIe && !isEdge && !isFirefox && !isOpera;+}

I previously attempted using platform service, but had service-loading issues. Fixed these in ca91456

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha ca914567f8b0543e4017b15cbf6442cb5c6dffb7

Remove duplicate useragent sniffing

view details

push time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     });   } +  /**+   * When the visibility state of the document changes to hidden,+   * send the layout jank score.+   */+  onVisibilityChange_() {+    if (this.win.document.visibilityState !== 'hidden') {+      return;+    }+    this.tickLayoutJankScore_();+  }++  /**+   * Tick the layout jank score metric.+   *+   * A value of the metric is recorded in under two names, `lj` and `lj-2`,+   * for the first two times the page transitions into a hidden lifecycle state+   * (when the page is navigated a way from, the tab is backgrounded for+   * another tab, or the user backgrounds the browser application).+   *+   * Since we can't reliably detect when a page session finally ends,+   * recording the value for these first two events should provide a fair+   * amount of visibility into this metric.+   */+  tickLayoutJankScore_() {+    if (!this.tickedFirstJankScore_) {+      this.tickDelta('lj', this.aggregateJankScore_);+      this.flush();+      this.tickedFirstJankScore_ = true;+      return;+    }+    if (!this.tickedSecondJankScore_) {+      this.tickDelta('lj-2', this.aggregateJankScore_);+      this.flush();+      this.tickedSecondJankScore_ = true;++      this.win.removeEventListener(+          'visibilitychange',+          this.onVisibilityChange_,+          {capture: true}+      );+      // const platform = Services.platformFor(this.win);

I duplicated the isSafari() checks in this file to avoid the cross-service dependency problem issue

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 431cd15cc06295f531f0329ba690f934c220dba7

Add import statement

view details

push time in 2 months

Pull request review commentampproject/amphtml

🐛✅Fix tickevent tests for Safari

 export class Performance {       list.getEntries().forEach(processEntry);       this.flush();     });-    observer.observe({entryTypes: entryTypesToObserve});++    // Wrap observer.observe() in a try statement for testing, because+    // Webkit throws an error if the entry types to observe are not natively

We won't be able to read metrics from Performance APIs that Webkit hasn't implemented yet like EventTiming and LayoutJank, but when they do we will start getting numbers.

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

🐛✅Fix tickevent tests for Safari

 export class Performance {       list.getEntries().forEach(processEntry);       this.flush();     });-    observer.observe({entryTypes: entryTypesToObserve});++    // Wrap observer.observe() in a try statement for testing, because+    // Webkit throws an error if the entry types to observe are not natively+    // supported.+    try {+      observer.observe({entryTypes: entryTypesToObserve});+    } catch (err) {+      console/*OK*/.warn(err);

Done

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 1aa1604876386f89ef6d27e0ca1609efac3f880a

Use dev() log instead of console

view details

push time in 2 months

Pull request review commentgoogle/WebFundamentals

Add notes on Safari quirks for hidden lifecycle transitions.

 The above code does three things: <aside class="warning">   <strong>Warning!</strong>   This code yields different results in different browsers, as the order-  (and reliability) of events has not been consistently implemented. To learn+  and reliability of events has not been consistently implemented. To learn

This small change makes it a bit more clear that reliability of the events across browsers is problematic.

ericandrewlewis

comment created time in 2 months

Pull request review commentgoogle/WebFundamentals

Add notes on Safari quirks for hidden lifecycle transitions.

 window.addEventListener('pagehide', (event) => {     logStateChange('terminated');   } }, {capture: true});++// Safari does not reliably fire the `pagehide` or `visibilitychange`+// events when closing a tab, so we have to use `beforeunload` with a+// timeout to check whether the default action was prevented.+// - https://bugs.webkit.org/show_bug.cgi?id=151610+// - https://bugs.webkit.org/show_bug.cgi?id=151234+// NOTE: we only add this to Safari because adding it to Firefox would+// prevent the page from being eligible for bfcache.

Done.

ericandrewlewis

comment created time in 2 months

Pull request review commentgoogle/WebFundamentals

Add notes on Safari quirks for hidden lifecycle transitions.

 that pertain to lifecycle and lists what states they may transition to and from.       point.</p>       <aside class="warning">         <strong>Warning:</strong>-        The <code>beforeunload</code> event should only be used to alert the-        user of unsaved changes. Once those changes are saved, the event should-        be removed. It should never be added unconditionally to the-        page, as doing so can hurt performance in some cases. See the-        <a href="#legacy-lifecycle-apis-to-avoid">legacy APIs section</a>-        for details.+        The <code>beforeunload</code> event should only be used in two cases:

Done.

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/WebFundamentals

Eric Lewis

commit sha 3a4ee4248e396ccbfc41d4c7f4eb0341e15bd7d9

Move Safari quirks to cross-browser section

view details

push time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha bfc5b2e35f6f7fdce015e2698539b6a6bdc90290

ESLint fix

view details

push time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 629cbdee949ee263390ff6933c2603b6515c0a72

Fix useragent reference bug

view details

Eric Lewis

commit sha ceeb0670df462e671399f08ffb07de1037c2efdf

Add Layout Jank extern to list of externs

view details

push time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha c52a9aacd23479c814b8372060fbd4cee86bb4f6

Add a local definition of Safari useragent checking to avoid test failure in cross-service dependency

view details

push time in 2 months

PR opened google/WebFundamentals

Add notes on Safari quirks for hidden lifecycle transitions.

What's changed, or what was fixed?

  • Add notes on Safari quirks for hidden lifecycle transitions.

Fixes: I didn't open an issue but can?

Target Live Date: ?

  • [ ] This has been reviewed and approved by (no one yet)
  • [x] I have run npm test locally and all tests pass.
  • [ ] I have added the appropriate type-something label.
  • [ ] I've staged the site and manually verified that my content displays correctly.

CC: @petele / @philipwalton

+33 -6

0 comment

1 changed file

pr created time in 2 months

create barnchericandrewlewis/WebFundamentals

branch : page-lifecycle-api-1

created branch time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 72c57e89ebd9a995a4e8449448e996a034dccf94

Renamed onPageHidden_ to onVisibilityChange_

view details

Eric Lewis

commit sha 9bdca3750ab233ca5423bc9b8fa62897a749f983

Add Closure Compiler definition for the Layout Jank API

view details

push time in 2 months

issue openedampproject/amphtml

Expose layout stability metrics

b/124533045

Layout Stability is a new metric that provides insight to how much elements move around on the page.

created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 58a141b84cd69e2c6812771409bb2fbe51cb23b1

Add lj and lj-2 to Tick Events documentation

view details

push time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     observer.observe({entryTypes: entryTypesToObserve});   } +  /**+   * Bind to various page lifecycle events to capture visibility state changes.+   * @see https://developers.google.com/web/updates/2018/07/page-lifecycle-api+   */+  registerLayoutJankHandler_() {+    // The visibility state of the document.+    let visibilityState = getVisibilityState(this.win.document);+    // Whether the `lj` metric was sent.+    let sentFirstJankScore = false;+    // Whether the `lj-2` metric was sent.+    let sentSecondJankScore = false;++    const handleVisibilityStateChange = nextState => {+      const previousState = visibilityState;+      if (previousState === nextState) {+        return;+      }+      visibilityState = nextState;++      if (nextState !== 'hidden') {+        return;+      }++      if (!sentFirstJankScore) {+        this.tickDelta('lj', this.aggregateJankScore_);+        this.flush();+        sentFirstJankScore = true;+        return;+      }+      if (!sentSecondJankScore) {+        this.tickDelta('lj-2', this.aggregateJankScore_);+        this.flush();+        sentSecondJankScore = true;+        return;+      }+    };++    ['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach(eventName => {+      this.win.addEventListener(eventName, () => handleVisibilityStateChange(getVisibilityState(this.win.document)), {capture: true});

Good catch - I moved the binding to the constructor to fix.

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     observer.observe({entryTypes: entryTypesToObserve});   } +  /**+   * Bind to various page lifecycle events to capture visibility state changes.+   * @see https://developers.google.com/web/updates/2018/07/page-lifecycle-api+   */+  registerLayoutJankHandler_() {+    // The visibility state of the document.+    let visibilityState = getVisibilityState(this.win.document);+    // Whether the `lj` metric was sent.+    let sentFirstJankScore = false;+    // Whether the `lj-2` metric was sent.+    let sentSecondJankScore = false;++    const handleVisibilityStateChange = nextState => {+      const previousState = visibilityState;+      if (previousState === nextState) {+        return;+      }+      visibilityState = nextState;++      if (nextState !== 'hidden') {+        return;+      }++      if (!sentFirstJankScore) {+        this.tickDelta('lj', this.aggregateJankScore_);+        this.flush();+        sentFirstJankScore = true;+        return;+      }+      if (!sentSecondJankScore) {+        this.tickDelta('lj-2', this.aggregateJankScore_);+        this.flush();+        sentSecondJankScore = true;+        return;+      }+    };++    ['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach(eventName => {

I might not have explained the use case clearly. We're interested in recording layout jank just when the user leaves the page. So checking the document.visibilityState whenever the visibilitychange event is fired seems sufficient for Chrome in my testing, and adding the beforeunload event for Safari as you mentioned.

Although a resume event may be fired when the document is in the hidden state, it seems this would be the result of a page transitioning from frozen to hidden, which I believe would happen when a user re-enters a backgrounded tab?

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 62d48d0836079615e7349ea5d8dac2c923e7dfbc

Correct Performance.onVisibilityChange_ binding

view details

push time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha db463fc26371338ab3c18766a14faeda04c3fc13

Remove extra line

view details

push time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     });   } +  /**+   * When the visibility state of the document changes to hidden,+   * send the layout jank score.+   */+  onVisibilityChange_() {+    if (this.win.document.visibilityState !== 'hidden') {+      return;+    }+    this.tickLayoutJankScore_();+  }++  /**+   * Tick the layout jank score metric.+   *+   * A value of the metric is recorded in under two names, `lj` and `lj-2`,+   * for the first two times the page transitions into a hidden lifecycle state+   * (when the page is navigated a way from, the tab is backgrounded for+   * another tab, or the user backgrounds the browser application).+   *+   * Since we can't reliably detect when a page session finally ends,+   * recording the value for these first two events should provide a fair+   * amount of visibility into this metric.+   */+  tickLayoutJankScore_() {+    if (!this.tickedFirstJankScore_) {+      this.tickDelta('lj', this.aggregateJankScore_);+      this.flush();+      this.tickedFirstJankScore_ = true;+      return;+    }+    if (!this.tickedSecondJankScore_) {+      this.tickDelta('lj-2', this.aggregateJankScore_);+      this.flush();+      this.tickedSecondJankScore_ = true;++      this.win.removeEventListener(+          'visibilitychange',+          this.onVisibilityChange_,+          {capture: true}+      );+      // const platform = Services.platformFor(this.win);

If I uncomment this code our tests fail, I assume because the platform service hasn't had a chance to load yet...and suggestions here?

Error: Expected service platform to be registered
    at Log.assert (usr/local/google/home/ericnyc/git/amphtml/src/log.js:343:17)
    at devAssert (usr/local/google/home/ericnyc/git/amphtml/src/log.js:728:29)
    at getServiceInternal (usr/local/google/home/ericnyc/git/amphtml/src/service.js:394:3)
    at getService (usr/local/google/home/ericnyc/git/amphtml/src/service.js:194:10)
    at Function.platformFor (usr/local/google/home/ericnyc/git/amphtml/src/services.js:317:7)
    at Performance.tickLayoutJankScore_ (usr/local/google/home/ericnyc/git/amphtml/src/service/performance-impl.js:342:33)
    at Performance.onVisibilityChange_ (usr/local/google/home/ericnyc/git/amphtml/src/service/performance-impl.js:310:10)
    at http://localhost:9876/usr/local/google/home/ericnyc/git/amphtml/test/unit/test-performance.js:1014:35
    at Array.forEach (<anonymous>)
    at Context.<anonymous> (usr/local/google/home/ericnyc/git/amphtml/test/unit/test-performance.js:1014:15)
ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     observer.observe({entryTypes: entryTypesToObserve});   } +  /**+   * Bind to various page lifecycle events to capture visibility state changes.+   * @see https://developers.google.com/web/updates/2018/07/page-lifecycle-api+   */+  registerLayoutJankHandler_() {+    // The visibility state of the document.+    let visibilityState = getVisibilityState(this.win.document);+    // Whether the `lj` metric was sent.+    let sentFirstJankScore = false;+    // Whether the `lj-2` metric was sent.+    let sentSecondJankScore = false;++    const handleVisibilityStateChange = nextState => {+      const previousState = visibilityState;+      if (previousState === nextState) {+        return;+      }+      visibilityState = nextState;++      if (nextState !== 'hidden') {+        return;+      }++      if (!sentFirstJankScore) {+        this.tickDelta('lj', this.aggregateJankScore_);+        this.flush();+        sentFirstJankScore = true;+        return;+      }+      if (!sentSecondJankScore) {+        this.tickDelta('lj-2', this.aggregateJankScore_);+        this.flush();+        sentSecondJankScore = true;+        return;+      }+    };++    ['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach(eventName => {+      this.win.addEventListener(eventName, () => handleVisibilityStateChange(getVisibilityState(this.win.document)), {capture: true});

Done.

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     observer.observe({entryTypes: entryTypesToObserve});   } +  /**+   * Bind to various page lifecycle events to capture visibility state changes.+   * @see https://developers.google.com/web/updates/2018/07/page-lifecycle-api+   */+  registerLayoutJankHandler_() {+    // The visibility state of the document.+    let visibilityState = getVisibilityState(this.win.document);+    // Whether the `lj` metric was sent.+    let sentFirstJankScore = false;+    // Whether the `lj-2` metric was sent.+    let sentSecondJankScore = false;++    const handleVisibilityStateChange = nextState => {+      const previousState = visibilityState;+      if (previousState === nextState) {+        return;+      }+      visibilityState = nextState;++      if (nextState !== 'hidden') {+        return;+      }++      if (!sentFirstJankScore) {+        this.tickDelta('lj', this.aggregateJankScore_);+        this.flush();+        sentFirstJankScore = true;+        return;+      }+      if (!sentSecondJankScore) {+        this.tickDelta('lj-2', this.aggregateJankScore_);+        this.flush();+        sentSecondJankScore = true;+        return;+      }+    };++    ['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach(eventName => {

Done.

If we only care about the change of a page from a hidden state ... it seems like we could just listen to the visibilitychange event here, and avoid pageshow and resume as well?

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 export class Performance {     observer.observe({entryTypes: entryTypesToObserve});   } +  /**+   * Bind to various page lifecycle events to capture visibility state changes.+   * @see https://developers.google.com/web/updates/2018/07/page-lifecycle-api+   */+  registerLayoutJankHandler_() {+    // The visibility state of the document.+    let visibilityState = getVisibilityState(this.win.document);+    // Whether the `lj` metric was sent.+    let sentFirstJankScore = false;+    // Whether the `lj-2` metric was sent.+    let sentSecondJankScore = false;++    const handleVisibilityStateChange = nextState => {+      const previousState = visibilityState;+      if (previousState === nextState) {+        return;+      }+      visibilityState = nextState;++      if (nextState !== 'hidden') {+        return;+      }++      if (!sentFirstJankScore) {+        this.tickDelta('lj', this.aggregateJankScore_);+        this.flush();+        sentFirstJankScore = true;+        return;+      }+      if (!sentSecondJankScore) {+        this.tickDelta('lj-2', this.aggregateJankScore_);+        this.flush();+        sentSecondJankScore = true;+        return;

Done, partially. Adding a comment on new code about issue in tests.

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Report a new tick event metric for Layout Jank

 function incOrDef(obj, name) {   } } +/**+ * Get the visibility state of the provided document.+ *+ * @param {Document} document+ */+function getVisibilityState(document) {

Done.

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Renovate Bot

commit sha e5329c59755fa03a44e595d0d7b0f909032f958d

Update dependency autoprefixer to v9.4.9 (#21059)

view details

Renovate Bot

commit sha 45563231066a70eca1d05cd2d9097375c9c94751

Update dependency karma-babel-preprocessor to v8 (#20315)

view details

Renovate Bot

commit sha 411a5aa258700e18510be3373013ae52b9bcd855

Update dependency gulp-git to v2.9.0 (#20240)

view details

Ali Ghassemi

commit sha d412590b7761f82a53c3712f4ce9e7d98a9465db

🐛 amp-animation scrolltimeline: bug fixes (#20915)

view details

Raghu Simha

commit sha bb111a6858543dc856d40b92b2b18b3b3c3e4617

✅ Skip failing performance test on Safari (#21061)

view details

Renovate Bot

commit sha 836345248ca328b2083c1e7f1eef698a7baaee49

Update dependency gulp-ava to v1 (#19904)

view details

William Chou

commit sha 04b8d09ef299225411bd3378fd496dc952375703

Simplify amp-state/bindReady race fix (#21052) * Simplify amp-state race fix. * Remove .only(). * Fix other bind tests.

view details

Alan Orozco

commit sha d47c488598dfda17f69515cff2390537386488bb

✨Accept canonical URL in proxy form (#21043) The local proxy form now accepts three valid forms (with or without protocol): ## Canonical URL https://www.theverge.com/2019/2/24/18236633/pizza-city-podcast-steve-dolinsky-chicago-new-york-pod-hunters ## AMPHTML URL https://www.theverge.com/platform/amp/2019/2/24/18236633/pizza-city-podcast-steve-dolinsky-chicago-new-york-pod-hunters ## Google Viewer URL https://www.google.com/amp/s/www.theverge.com/platform/amp/2019/2/24/18236633/pizza-city-podcast-steve-dolinsky-chicago-new-york-pod-hunters

view details

Alan Orozco

commit sha c33eb82d37b2af1f27728b15756946a631efd6e8

📖 Simplify docking example (#21037) TIL (actually yesterday) of `amp-animation.reverse`. This means we can have only one animation and `reverse` it on `undock`. ABE: ampproject/amp-by-example#1835

view details

Raghu Simha

commit sha 342d62eaaa7e7b307a0675c09b09d3da28edb237

🏗🐛 Fix broken single pass build (#21075)

view details

Renovate Bot

commit sha c7a481d69da31dff4a2c3f1a8e9bf3dc9695107b

Update dependency nodemon to v1.18.10 (#21076)

view details

Renovate Bot

commit sha 7469d3922699fbe4497b20bb9b7434e8edf3a1de

Update dependency karma-source-map-support to v1.4.0 (#21069)

view details

Renovate Bot

commit sha 3bd9143a6c5dce2f0c868615bdb5757604ed38fc

Update dependency karma-coverage-istanbul-reporter to v2.0.5 (#21068)

view details

Renovate Bot

commit sha a8f6e7214c7cc9b88aee43ab693a26cc8be50e60

Update dependency fuse.js to v3.4.2 (#21066)

view details

Renovate Bot

commit sha b360f1f674ed4071abc304ad88f62c273fa70129

Update dependency eslint-plugin-jsdoc to v4.1.1 (#21065)

view details

Renovate Bot

commit sha ee8daa811e612a292a80c65b6e483bc24e6759e7

Update dependency moment to v2.24.0 (#21073)

view details

Alan Orozco

commit sha 444fc388a7c5f3991a5ade443af0c7992df89c88

♻️✨ amp-fx=float-in-(top|bottom) (#20905) Partial for #20881. Base implementation for `amp-fx="float-in-(top|bottom)"`. Slides elements in-and-out accordingly. Matches behavior of Google viewer's sliding header, see http://go/amp-viewer-scroll and http://go/amp-viewer-scroll-thresholds internally. Demo: https://scroll-toggle.glitch.me/ Also: * refactors `amp-fx-collection` for types and size. (~10% down from total bundle) * adds a bunch of string → types tests (and killed a splice bug, thanks @amphtml-lgtm-bot!)

view details

Alan Orozco

commit sha 420db9d7187a935585e54dbacca175a82e916109

✨auto-lightbox carousels under experiment (#20910) * Introduces criteria to accept any carousel that: 1. Has one image on every slide 2. Has no valid `on=tap` actions. * Since `amp-img` has to be measured against the slide element, some APIs are now async. * Introduces a `mixed` manual test for several cases.

view details

Sepand Parhami

commit sha 1dfd58779cc17a683fa3ddeb58aef11c50fb04f2

Rename amp-carousel 0.2 to amp-base-carousel (#21034)

view details

Renovate Bot

commit sha 8f05fc926e973de829dc3eb140fb2dd573ec0384

Update dependency mocha to v6 (#21091)

view details

push time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha b530927c394d509ae6279d549fc20bfde4e3291b

Fix property restoration logic

view details

push time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 8ce5e70a187aa96565d8a5c089200c3a661a60a1

Create Event instead of TouchEvent which isn't supported by Safari

view details

push time in 2 months

pull request commentampproject/amphtml

✨ Introduce `fid-polyfill` tickevent.

@lannka The polyfill is 738 bytes gzipped / 1.25KB uncompressed. It is conditionally embedded as an inline script in the document's head by the AMP cache, since it needs to run before paint in order to capture early user input correctly.

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 81634266b91d3fa31922c10bb10bcbbc0af751c6

Fix eslint issues

view details

push time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha fec9a9238cced7a0f7b7d040372d7aa68bffee62

Add comment to allow legit usage of console.warn

view details

push time in 2 months

PR opened ampproject/amphtml

✨ Introduce `fid-polyfill` tickevent.

See https://github.com/GoogleChromeLabs/first-input-delay

Fixes #21121

+50 -1

0 comment

3 changed files

pr created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 929445908d32dddad916d576f839d409416c8ab0

Introduce `fid-polyfill` tickevent. See https://github.com/GoogleChromeLabs/first-input-delay Fixes #21121

view details

push time in 2 months

issue openedampproject/amphtml

Expose first input delay value via polyfill

b/124758890

created time in 2 months

create barnchericandrewlewis/amphtml

branch : patch-6

created branch time in 2 months

PR opened ampproject/amphtml

🐛✅Fix tickevent tests for Safari

Fixes #21062

+11 -7

0 comment

2 changed files

pr created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 6337ba3fe694e0d3f3b78e41ec745f2a5885624b

Fix tickevent tests for Safari Fixes #21062

view details

push time in 2 months

create barnchericandrewlewis/amphtml

branch : patch-72

created branch time in 2 months

issue commentampproject/amphtml

Unmute some performance tests

I can't reproduce the error myself (here's notes on that), but I understand the problem.

Webkit validates the entryTypes passed to a call to PerformanceObserver.observe() like this:

perfObserver.observe({entryTypes: ['some', 'entry', 'types']});

If it sees all entryTypes are invalid, it throws a TypeError.

This is the case in our tests, where we stub properties on the window object to pretend that APIs like Event Timing exist in order to test the implementation of our metrics collection. Since these APIs don't actually exist and fail this validation, we see the TypeError in Safari.

lannka

comment created time in 2 months

push eventericandrewlewis/nvm

Jordan Harband

commit sha f195dc8525f42e298b19ffa5c8feef9570c58378

Update README.md Co-Authored-By: ericandrewlewis <eric.andrew.lewis@gmail.com>

view details

push time in 2 months

PR opened ampproject/amphtml

✨ Report a new tick event metric for Layout Jank

This introduces two new viewer tick events to track layout jank.

lj is fired the first time the page transitions into the hidden lifecycle state, and lj-2 is fired the second time the page transitions into the hidden lifecycle state.

See Explainer: Layout Stability Metric.

+78 -0

0 comment

1 changed file

pr created time in 2 months

create barnchericandrewlewis/amphtml

branch : patch-5

created branch time in 2 months

push eventericandrewlewis/emoji-mosaic

Eric Andrew Lewis

commit sha 76f8a54eefb341f4a66e2fb37bff9c44deeac501

Add nopoo mode

view details

push time in 2 months

delete branch ericandrewlewis/amphtml

delete branch : patch-2

delete time in 2 months

PR opened creationix/nvm

Add note about what version of node new shells run with.

Fixes #2000

+2 -0

0 comment

1 changed file

pr created time in 2 months

push eventericandrewlewis/nvm

Eric Lewis

commit sha 42fb5ea86435bacbbdf444eba3e43b02329fe38b

Add note about what version of node new shells run with. Fixes #2000

view details

push time in 2 months

create barnchericandrewlewis/nvm

branch : patch-1

created branch time in 2 months

fork ericandrewlewis/nvm

Node Version Manager - Simple bash script to manage multiple active node.js versions

fork in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha ba2242c480123a8c50e8053aea0ca375345f3902

Add more robust page session end support

view details

push time in 2 months

Pull request review commentampproject/amphtml

✨ Record new tick event fid (first input delay).

 describes.realWin('performance with experiment', {amp: true}, env => {     });   }); });++describes.realWin('PeformanceObserver metrics', {amp: true}, env => {+  // A fake implementation of PerformanceObserver.+  class PerformanceObserverImpl {+    constructor(callback) {+      this.options = {};+      this.callback_ = callback;+      this.isObserving = false;++    }++    observe(options) {+      this.options = options;+      this.isObserving = true;++    }++    disconnect() {+      this.isObserving = false;+    }++    /**+     * Trigger the Observer's callback.+      * @param {!Array} entries+      */+    triggerCallback(entries) {+      this.callback_(entries, this);+    }+  }++  describe('should forward paint metrics for performance entries', () => {+    it('created before performance service registered', () => {+      // Pretend that the PaintTiming API exists.+      env.win.PerformancePaintTiming = true;++      const entries = [{+        duration: 1,+        entryType: 'paint',+        name: 'first-paint',+        startTime: 10,+      },+      {+        duration: 5,+        entryType: 'paint',+        name: 'first-contentful-paint',+        startTime: 10,+      }];+      const getEntriesByType = env.sandbox.stub();+      getEntriesByType.withArgs('paint').returns(entries);+      getEntriesByType.returns([]);+      env.sandbox.stub(env.win.performance, 'getEntriesByType')+          .callsFake(getEntriesByType);++      installPerformanceService(env.win);++      const perf = Services.performanceFor(env.win);++      expect(perf.events_.length).to.equal(2);+      expect(perf.events_[0])+          .to.be.jsonEqual({+            label: 'fp',+            delta: 11,+          },+          {+            label: 'fcp',+            delta: 15,+          });++      delete env.win.PerformancePaintTiming;+    });++    it('created after performance service registered', () => {+      // Pretend that the PaintTiming API exists.+      env.win.PerformancePaintTiming = true;++      // Stub and fake the PerformanceObserver constructor.+      const PerformanceObserverStub = env.sandbox.stub();++      let performanceObserver;+      PerformanceObserverStub.callsFake(callback => {+        performanceObserver = new PerformanceObserverImpl(callback);+        return performanceObserver;+      });+      env.sandbox.stub(env.win, 'PerformanceObserver')+          .callsFake(PerformanceObserverStub);++      installPerformanceService(env.win);++      const perf = Services.performanceFor(env.win);++      const entries = [{+        duration: 1,+        entryType: 'paint',+        name: 'first-paint',+        startTime: 10,+      },+      {+        duration: 5,+        entryType: 'paint',+        name: 'first-contentful-paint',+        startTime: 10,+      }];+      const list = {+        getEntries() {+          return entries;+        },+      };+      // Fake a triggering of the firstInput event.+      performanceObserver.triggerCallback(list);+      expect(perf.events_.length).to.equal(2);+      expect(perf.events_[0])+          .to.be.jsonEqual({+            label: 'fp',+            delta: 11,+          },+          {+            label: 'fcp',+            delta: 15,+          });+      delete env.win.PerformanceEventTiming;+    });+  });++  describe('should forward first input metrics for performance entries', () => {+    it('created before performance service registered', () => {+      // Pretend that the EventTiming API exists.+      env.win.PerformanceEventTiming = true;++      const entries = [{+        cancelable: true,+        duration: 8,+        entryType: 'firstInput',+        name: 'mousedown',+        processingEnd: 105,+        processingStart: 103,+        startTime: 100,+      }];+      const getEntriesByType = env.sandbox.stub();+      getEntriesByType.withArgs('firstInput').returns(entries);+      getEntriesByType.returns([]);+      env.sandbox.stub(env.win.performance, 'getEntriesByType')+          .callsFake(getEntriesByType);++      installPerformanceService(env.win);++      const perf = Services.performanceFor(env.win);++      expect(perf.events_.length).to.equal(1);+      expect(perf.events_[0])+          .to.be.jsonEqual({+            label: 'fid',+            delta: 3,+          });++      delete env.win.PerformanceEventTiming;+    });++    it('created after performance service registered', () => {+      // Pretend that the EventTiming API exists.+      env.win.PerformanceEventTiming = true;++      // Stub and fake the PerformanceObserver constructor.+      const PerformanceObserverStub = env.sandbox.stub();++      let performanceObserver;+      PerformanceObserverStub.callsFake(callback => {+        performanceObserver = new PerformanceObserverImpl(callback);+        return performanceObserver;+      });+      env.sandbox.stub(env.win, 'PerformanceObserver')+          .callsFake(PerformanceObserverStub);++      installPerformanceService(env.win);++      const perf = Services.performanceFor(env.win);++      const entries = [{+        cancelable: true,+        duration: 8,+        entryType: 'firstInput',+        name: 'mousedown',+        processingEnd: 105,+        processingStart: 103,+        startTime: 100,+      }];+      const list = {+        getEntries() {+          return entries;+        },+      };+      // Fake a triggering of the firstInput event.+      performanceObserver.triggerCallback(list);+      expect(perf.events_.length).to.equal(1);+      expect(perf.events_[0])+          .to.be.jsonEqual({+            label: 'fid',+            delta: 3,+          });+      delete env.win.PerformanceEventTiming;

Hmm - one of the tests fakes env.win.PerformancePaintTiming and the three others fake env.win.PerformanceEventTiming. We'll introduce other faked properties in this manner (like window.PerformanceLayoutJank so I think leaving these in the test cases is okay?

ericandrewlewis

comment created time in 2 months

create barnchericandrewlewis/amphtml

branch : patch-2

created branch time in 2 months

Pull request review commentcppchriscpp/nes-starter-kit

For functions that don't accept parameters, add void in parenthesis.

 // Contains functions to help with working with multle PRG/CHR banks -// Maximum level of recursion to allow with banked_call and similar functions. 

My editor automatically trims white space when I save a file - I can undo these changes if they're undesired

ericandrewlewis

comment created time in 2 months

PR opened cppchriscpp/nes-starter-kit

For functions that don't accept parameters, add void in parenthesis.

This avoids conflicting type errors in some versions of cc65 and is closer to what C's type system expects.

See #18.

+67 -67

0 comment

14 changed files

pr created time in 2 months

create barnchericandrewlewis/nes-starter-kit

branch : patch-1

created branch time in 2 months

fork ericandrewlewis/nes-starter-kit

A Beginner's Guide and toolkit for NES game creation.

fork in 2 months

push eventericandrewlewis/amphtml

Raghu Simha

commit sha f70a454b64219044beb4ad4bba874ff000d68f53

🏗 Enable verbose logging for sauce connect (#20716)

view details

Carlos Vializ

commit sha 9f78741b5a39356b51386405eba797c9949be15d

✨Launch amp-inputmask (#20661) * Launch amp-inputmask * Tests are flaky

view details

Benjamin Harrigan

commit sha a5b0f7aea15f517e1ff8a1540c05d6722309afdc

Correctly validate numeric outputs to default values in amp-bind (#20659)

view details

Aaron Turner

commit sha df0886a079974a28e64de4879d1a8eeeff41c11e

🐛Re-implemented "Fixed NonXHR GET on amp-form with Async Input Elements" (#20667) * Re-implemented original PR * Think I know what broke prod. Left todo * Fixed no event NonXHR GET Submits * Fixed tests I originally broke :p * Made requested changes * Fixed Example submission, made last PR comment

view details

Sepand Parhami

commit sha 09b9848c9bb38a37622b6b28da42d7bb22696542

Fixes for lightbox gallery and shadow docs. (#20712) - Use AMP.win instead of global. - Do the transition within the shadow doc, since that is where we are putting the styles for the transition.

view details

Raghu Simha

commit sha 7d695c01471db62f45f4af7f972075122f3250f6

🏗 Capture console output and verbose logging during sauce connect failures (#20729)

view details

Gabriel Majoulet

commit sha c72df4804cfc8b49892b0aa7e81c25c5c060cdcc

Story page attachments validation. (#20673) * Story page attachments validation. * Validation error test case, and A-Z the list of descendants. * Test that cta-layer and page-attachment can't coexist within the same page. * Reviews.

view details

Sepand Parhami

commit sha 9895d70e8afc9e2ac5e38655e5509c57f87c98d1

Fix lightbox closing when opened from a carousel. (#20730) The wrong selector is used here, causing an assert to fail.

view details

Enrique Marroquin

commit sha 8b6c1cba714949233c085899661844ac8481c533

replace common signal CHANGE_SIZE_END with a change size event. (#20728)

view details

Pet Ramanudom

commit sha 4b1dbfb1c8c69aaf5994fc07b37966cd939ec2eb

✨Amend preloading to work with branching (#20611) * implemented changes still need to fix tests * fixed tests * removed console.logs * Add comment * addressed PR comments * fixed lint issues * Oops * revert changes * added more tests, reverted accidental change in validator.js * removed excess space that linter didnt catch * addressed nits

view details

Caroline Liu

commit sha 4cd12f1f5dc814f3df7cd35d5849c545663cab04

🐛Modify amp-pinterest.css from displaying "Pin It" to "Save" as a button (#20706) * change references from 'Pin It' to 'Save' in amp-pinterest * Modify css for follow button and round logo classes * Modify Save Button class styles * Modify amp-pinterest classes to display colored and language-specific Save buttons. * Modify count-beside and count-below css classes to make Save button visible again. * Alphabetize css attributes. * Alphabetize css attributes. * Fix dimensions on save-button-tall. * Resolve misplacement of -count-above classes. * Add bottom arrow to -bubble-above. * Remove 'content' attribute. * Add side array to -bubble-beside. * Revert examples/pinterest.amp.html * Update -bubble-above and -bubble-beside classes to match fixed dimensions. * Whitelist renamed file save-button.js * Update SVG data-uri to be encoded as utf-8. * Refactor SVG data uri to remove inline style tags. * Refactor gray color classes to display the logo on Save Buttons in grayscale. * Revert changes to gray logo -- Realized this is not allowed in brand guidelines. * Replace SVG inline data with converted base64 data to restore a white border around the Pinterest logo. * Default button color to red instead of gray. * Update PinWidget.js (embedded pins) to show a 'Save' button instead of a 'Pin It' button. * Update styling for gray buttons to emulate bubble styling. * Revert changing to logging request. * Revert change to logging request.

view details

delima02

commit sha d87152df1e45a693bc5757bddb396cc09afdb799

🐛 Have purifier.js allow unknown protocols (#20710) * Have purifier.js allow unknown protocols. * Add unit test for allowing arbitrary protocols. * Add required 'target' attribute to tags in arbitrary protocols test. * Lint fix for unknown protocols test.

view details

Alan Orozco

commit sha c2e23a85fb10a870eaf25c772238bbaea6d2c647

🏗Move `amphtml-validator` to dev dependency (#20742)

view details

Sepand Parhami

commit sha 759ad97262ed64d15ca02fc2d76d86a098ef8c7b

Fix carousel e2e tests. (#20743) - Change approach used for setting the window size to work in headless mode. - Skip a test that no longer works with the current approach.

view details

Matthias Rohmer

commit sha 0937333cb3f4d1b09bd41f86db565c2dcda7ed3a

:book: Add frontmatter to reference docs and transform attribute listings to tables (#20684) * 📝 Add frontmatter to reference and rewrite lists to tables * 📝 Update links marked by link checker * 🐛 Update links marked by link checker

view details

Raghu Simha

commit sha 1dc457879632e0d27180108fb51ef70b02f7d2d4

Run push builds against revert branches (#20749)

view details

Jon Newmuis

commit sha 389ff3bac340dc622f97421ccba04975e00fb990

Update amp-story.md (#20771)

view details

Raghu Simha

commit sha 8e6bf1980af92afab3db6965347772f15a44084d

🏗🐛 Roll back sauce connect version to 4.5.1 (#20767)

view details

Alan Orozco

commit sha 5176a21fe15b662c1c0b3ada65f9d3615f545ab3

📖 Document auto-lightbox treatment (#20757) Google internal related: go/amp-auto-lightbox Reflects status of working code after #20751, #20761

view details

keithwrightbos

commit sha bbbce14b3c8792600a1041b0822e5b7eb5cf669d

Doubleclick/AdSense Fast fetch: Checksum based validation (#20768) * Initial commit * Remove .only from test

view details

push time in 2 months

issue commentcppchriscpp/nes-starter-kit

Errors in build on a mac

Thanks for looking! I may poke at this a bit, understanding that the project does not support non-Windows environments. Maybe these notes will be useful for the project, or someone else going down a similar path.

Include path errors

I hit a few include path issues along the way, which my previous comment included one of:

temp/base.asm(1): Error: Cannot open include file `tools/cc65_config/game_constants.asm': No such file or directory

These I fixed by editing the Makefile, and setting an --include-dir for the project's root directory like so:

 temp/%.s: %.c $(SOURCE_HEADERS)
-       $(MAIN_COMPILER) -Oi $< --add-source --include-dir ./tools/cc65/include -o $(patsubst %.o, %.s, $@)
+       $(MAIN_COMPILER) -Oi $< --add-source --include-dir ./tools/cc65/include --include-dir ./ -o $(patsubst %.o, %.s, $@)
 temp/%.s: %.c $(SOURCE_HEADERS)
-       $(MAIN_COMPILER) -Oi $< --add-source --include-dir ./tools/cc65/include -o $(patsubst %.o, %.s, $@)
+       $(MAIN_COMPILER) -Oi $< --add-source --include-dir ./tools/cc65/include --include-dir ./ -o $(patsubst %.o, %.s, $@)

Conflicting type errors

I then saw a lot of errors like these:

source/graphics/fade_animation.c(25): Error: Conflicting types for `fade_in'

This is because at least my version of cc65 expects a function definition that is void to include the void keyword inside the parens like so:

void fade_in(void);

I guess if you leave them out C thinks that the method accepts any number of parameters, and somehow that doesn't jive with the actual implementations of these functions with no params.

I think this might be a good change for the repo, although if it's already working for others maybe not.

Symbols

I think the Symbols definition in the repo may be cc65 2.13.x specific. You're right, brew installs cc65 v2.17. I ended up futzing with the syntax instead of running the dockerized version just yet.

 SYMBOLS {
+   __STACKSIZE__: type = weak, value = $0500;      # 5 pages stack
-    __STACKSIZE__ = $0500;     # 5 pages stack
-       
     # WARNING: If you change this next variable, you also need to update its sibling _contants.asm file, in the same
     #          folder. The value of SYS_PRG_BANKS must equal the value of NES_PRG_BANKS
-       NES_PRG_BANKS = 8;                      # number of 16K PRG banks, change to 2 for NROM256
-       NES_CHR_BANKS = 16;                     # number of 8K CHR banks (If using 4k, divide by 2!)
+       NES_PRG_BANKS: type = weak, value = 8;                  # number of 16K PRG banks, change to 2 for NROM256
+       NES_CHR_BANKS: type = weak, value = 16;                         # number of 8K CHR banks (If using 4k, divide by 2!)
 }

Finally I can get to the ld65 step ... but for some reason the asm files end up with references to labels that don't exist... like these

Unresolved external `tossubax' referenced in:
  temp/map_sprites.s(741)
  temp/map_sprites.s(985)
  temp/map.s(1506)
Unresolved external `zerobss' referenced in:
  ./source/neslib_asm/crt0.asm(205)
ld65: Error: 48 unresolved external(s) found - cannot create output file
make: *** [rom/starter.nes] Error 1
ericandrewlewis

comment created time in 2 months

issue openedcppchriscpp/nes-starter-kit

Errors in build on a mac

This is my first time posting in this repository. Thanks for building this starter kit to make on-boarding to NES development easier!

I work on a mac and I'm attempting to build the project. Do you want to support the mac environment for this project, or want users to be in a Windows environment?

When I execute make run I get

16:22 $ make run
cmd /c start rom/starter.nes
make: cmd: No such file or directory
make: *** [run] Error 1

I can run the rom/starter.nes target directly though, but get an error:

16:30 $ make rom/starter.nes
./tools/cc65/bin/ca65 temp/base.asm -o temp/crt0.o -D SOUND_BANK=0
make: ./tools/cc65/bin/ca65: Permission denied
make: *** [temp/crt0.o] Error 1

Since I've installed the cc65 toolchain with brew, I change the MAIN_COMPILER, MAIN_ASM_COMPILER, and MAIN_LINKER definitions in the Makefile to the path-available programs, like MAIN_COMPILER=cc65

I then get an error

16:30 $ make rom/starter.nes
ca65 temp/base.asm -o temp/crt0.o -D SOUND_BANK=0
temp/base.asm(1): Error: Cannot open include file `tools/cc65_config/game_constants.asm': No such file or directory
temp/base.asm(2): Error: Cannot open include file `source/neslib_asm/crt0.asm': No such file or directory
make: *** [temp/crt0.o] Error 1

created time in 2 months

pull request commentampproject/amphtml

✨ Record new tick event fid (first input delay).

Should we add this new tick event to TICKEVENTS.md?

Sure - I added documentation for that.

@lannka / @calebcordry this is now ready for re-review.

ericandrewlewis

comment created time in 2 months

Pull request review commentampproject/amphtml

✨ Record new tick event fid (first input delay).

 export class Performance {     observer.observe({entryTypes: ['paint']});   } +  /**+   * Reports first input delay.+   * See https://wicg.github.io/event-timing/+   */+  registerEventTimingObserver_() {+    if (!this.win.PerformanceEventTiming) {+      return;+    }+    // Chrome doesn't implement the buffered flag for PerformanceObserver.+    // That means we need to read existing entries and maintain state+    // as to whether we have reported a value yet, since in the future it may+    // be reported twice.+    // https://bugs.chromium.org/p/chromium/issues/detail?id=725567+    let recordedFirstInputDelay = false;+    const processEntry = entry => {+      if (recordedFirstInputDelay) {+        return;+      }+      this.tick('fid', entry.processingStart - entry.startTime);

I created a separate extern for these definitions for now.

Maybe this should be added to closure-compiler itself - I'll follow-up there if so. Defining our own extern in this project allows us to move forward with this feature for the moment.

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha db32ac395c830ba03d1d49dc5c5e13bb30e36499

ESLint fixes

view details

push time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 03c4526b5516e207aec48e7ecf3d9f55fd76404e

Prefer sandbox.stub() over sinon.stub()

view details

push time in 2 months

issue openedgoogle/closure-compiler

Event Timing API externs

The Event Timing API is in Editor's Draft status.

Should the definitions be included? At what point in the standards process are definitions created in the compiler?

Glad to offer a PR if it makes sense to introduce these.

created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 4a898a94e7a9c5713cd1c463c012072234426e35

Add an Event Timing Closure Compiler externs definition

view details

push time in 2 months

Pull request review commentampproject/amphtml

✨ Record new tick event fid (first input delay).

 export class Performance {     observer.observe({entryTypes: ['paint']});   } +  /**+   * Reports first input delay.+   * See https://wicg.github.io/event-timing/+   */+  registerEventTimingObserver_() {+    if (!this.win.PerformanceEventTiming) {+      return;+    }+    // Chrome doesn't implement the buffered flag for PerformanceObserver.+    // That means we need to read existing entries and maintain state+    // as to whether we have reported a value yet, since in the future it may+    // be reported twice.+    // https://bugs.chromium.org/p/chromium/issues/detail?id=725567+    let recordedFirstInputDelay = false;+    const processEntry = entry => {+      if (recordedFirstInputDelay) {+        return;+      }+      this.tick('fid', entry.processingStart - entry.startTime);+      recordedFirstInputDelay = true;+    };+    const observer = new this.win.PerformanceObserver(list => {

Yeah let's do it - we'll have more perf metrics to record in the future. Done.

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha f3ec8fc3f9f63bcb475a292f3b5da5607c1d1390

Refactor to use a single PerformanceObserver

view details

push time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 1a267d1d825d31c4eda2c85a1851d5497d691563

Add first input delay documentation

view details

push time in 2 months

Pull request review commentampproject/amphtml

✨ Record new tick event fid (first input delay).

 describes.realWin('performance with experiment', {amp: true}, env => {     });   }); });++describes.realWin('performance with firstInput events', {amp: true}, env => {+  describe('should forward firstInput events as a fid tick event', () => {+    it('before performance service registered', () => {+      // Pretend that the EventTiming API exists.+      env.win.PerformanceEventTiming = true;++      //+      const earlyEntries = [{+        cancelable: true,+        duration: 8,+        entryType: 'firstInput',+        name: 'mousedown',+        processingEnd: 105,+        processingStart: 103,+        startTime: 100,+      }];+      const getEntriesByType = sinon.stub();+      getEntriesByType.withArgs('firstInput').returns(earlyEntries);+      getEntriesByType.returns([]);+      sinon.replace(env.win.performance, 'getEntriesByType', getEntriesByType);++      installPerformanceService(env.win);++      const perf = Services.performanceFor(env.win);++      expect(perf.events_.length).to.equal(1);+      expect(perf.events_[0])+          .to.be.jsonEqual({+            label: 'fid',+            delta: 3,+          });++      delete env.win.PerformanceEventTiming;+    });++    // A fake implementation of PerformanceObserver.+    class PerformanceObserverImpl {+      constructor(callback) {+        this.options = {};+        this.callback_ = callback;+        this.isObserving = false;++      }++      observe(options) {+        this.options = options;+        this.isObserving = true;++      }++      disconnect() {+        this.isObserving = false;+      }++      /**+       * Trigger the Observer's callback.+        * @param {!Array} entries+        */+      triggerCallback(entries) {+        this.callback_(entries, this);+      }+    }++    it('after performance service registered', () => {+      // Pretend that the EventTiming API exists.+      env.win.PerformanceEventTiming = true;++      // Stub and fake the PerformanceObserver constructor.+      const PerformanceObserverStub = sinon.stub();++      // First registerPaintTimingObserver_ will request an instance+      PerformanceObserverStub.onCall(0).callsFake(callback => {+        return new PerformanceObserverImpl(callback);+      });++      // Then registerEventTimingObserver_ will, which is the one we want to+      // interact with.+      let performanceObserver;+      PerformanceObserverStub.onCall(1).callsFake(callback => {+        performanceObserver = new PerformanceObserverImpl(callback);+        return performanceObserver;+      });+      sinon.replace(env.win, 'PerformanceObserver', PerformanceObserverStub);

Done this

ericandrewlewis

comment created time in 2 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 403c04df3485961bc3ea93f387f3c9441746a346

Use tickDelay instead of tick

view details

Eric Lewis

commit sha eb5a101355f47105877ab099be7e260f3fe69215

Prefer the sandbox stubbing method over sinon.replace

view details

push time in 2 months

Pull request review commentampproject/amphtml

✨ Record new tick event fid (first input delay).

 export class Performance {     observer.observe({entryTypes: ['paint']});   } +  /**+   * Reports first input delay.+   * See https://wicg.github.io/event-timing/+   */+  registerEventTimingObserver_() {+    if (!this.win.PerformanceEventTiming) {+      return;+    }+    // Chrome doesn't implement the buffered flag for PerformanceObserver.+    // That means we need to read existing entries and maintain state+    // as to whether we have reported a value yet, since in the future it may+    // be reported twice.+    // https://bugs.chromium.org/p/chromium/issues/detail?id=725567+    let recordedFirstInputDelay = false;+    const processEntry = entry => {+      if (recordedFirstInputDelay) {+        return;+      }+      this.tick('fid', entry.processingStart - entry.startTime);

This line is throwing this error in Travis CI:

src/service/performance-impl.js:235: ERROR - Property processingStart never defined on entry
      this.tick('fid', entry.processingStart - entry.startTime);
                             ^^^^^^^^^^^^^^^

I tried adding an annotation of PerformanceEntry for the entry parameter like this:

/**
 * @param {PerformanceEntry} entry
 */

However, the processingStart property is part of the new PerformanceEventTiming interface, and doesn't seem to be defined on the PerformanceEntry type. Which makes sense - the Event Timing API is in Editor's Draft status.

I tried specifying an unknown type inline:

this.tick('fid', (/** @type {?} */ (entry)).processingStart - entry.startTime);

but the compiler didn't like this either:

src/service/performance-impl.js:235: ERROR - Property processingStart never defined on ?
      this.tick('fid', (/** @type {?} */ (entry)).processingStart - entry.startTime);
                                                  ^^^^^^^^^^^^^^^

Any suggestion here?

ericandrewlewis

comment created time in 2 months

pull request commentampproject/amphtml

✨ Record new tick event fid (first input delay).

Hey @lannka - can you review?

ericandrewlewis

comment created time in 3 months

Pull request review commentampproject/amphtml

✨ Record new tick event fid (first input delay).

 describes.realWin('performance with experiment', {amp: true}, env => {     });   }); });++describes.realWin('performance with firstInput events', {amp: true}, env => {+  describe('should forward firstInput events as a fid tick event', () => {+    it('before performance service registered', () => {+      // Pretend that the EventTiming API exists.+      env.win.PerformanceEventTiming = true;++      //+      const earlyEntries = [{+        cancelable: true,+        duration: 8,+        entryType: 'firstInput',+        name: 'mousedown',+        processingEnd: 105,+        processingStart: 103,+        startTime: 100,+      }];+      const getEntriesByType = sinon.stub();+      getEntriesByType.withArgs('firstInput').returns(earlyEntries);+      getEntriesByType.returns([]);+      sinon.replace(env.win.performance, 'getEntriesByType', getEntriesByType);++      installPerformanceService(env.win);++      const perf = Services.performanceFor(env.win);++      expect(perf.events_.length).to.equal(1);+      expect(perf.events_[0])+          .to.be.jsonEqual({+            label: 'fid',+            delta: 3,+          });++      delete env.win.PerformanceEventTiming;+    });++    // A fake implementation of PerformanceObserver.+    class PerformanceObserverImpl {+      constructor(callback) {+        this.options = {};+        this.callback_ = callback;+        this.isObserving = false;++      }++      observe(options) {+        this.options = options;+        this.isObserving = true;++      }++      disconnect() {+        this.isObserving = false;+      }++      /**+       * Trigger the Observer's callback.+        * @param {!Array} entries+        */+      triggerCallback(entries) {+        this.callback_(entries, this);+      }+    }++    it('after performance service registered', () => {+      // Pretend that the EventTiming API exists.+      env.win.PerformanceEventTiming = true;++      // Stub and fake the PerformanceObserver constructor.+      const PerformanceObserverStub = sinon.stub();++      // First registerPaintTimingObserver_ will request an instance+      PerformanceObserverStub.onCall(0).callsFake(callback => {+        return new PerformanceObserverImpl(callback);+      });++      // Then registerEventTimingObserver_ will, which is the one we want to+      // interact with.+      let performanceObserver;+      PerformanceObserverStub.onCall(1).callsFake(callback => {+        performanceObserver = new PerformanceObserverImpl(callback);+        return performanceObserver;+      });+      sinon.replace(env.win, 'PerformanceObserver', PerformanceObserverStub);

Is this the best way to stub a class constructor?

ericandrewlewis

comment created time in 3 months

Pull request review commentampproject/amphtml

✨ Record new tick event fid (first input delay).

 describes.realWin('performance with experiment', {amp: true}, env => {     });   }); });++describes.realWin('performance with firstInput events', {amp: true}, env => {+  describe('should forward firstInput events as a fid tick event', () => {+    it('before performance service registered', () => {+      // Pretend that the EventTiming API exists.+      env.win.PerformanceEventTiming = true;++      //+      const earlyEntries = [{+        cancelable: true,+        duration: 8,+        entryType: 'firstInput',+        name: 'mousedown',+        processingEnd: 105,+        processingStart: 103,+        startTime: 100,+      }];+      const getEntriesByType = sinon.stub();+      getEntriesByType.withArgs('firstInput').returns(earlyEntries);+      getEntriesByType.returns([]);+      sinon.replace(env.win.performance, 'getEntriesByType', getEntriesByType);++      installPerformanceService(env.win);++      const perf = Services.performanceFor(env.win);++      expect(perf.events_.length).to.equal(1);+      expect(perf.events_[0])+          .to.be.jsonEqual({+            label: 'fid',+            delta: 3,+          });++      delete env.win.PerformanceEventTiming;+    });++    // A fake implementation of PerformanceObserver.+    class PerformanceObserverImpl {

Is this the best way to fake a class with Sinon?

ericandrewlewis

comment created time in 3 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 273ee18bed052a91f5e55bb078fc9d57bd06f65c

Fix variable name

view details

push time in 3 months

Pull request review commentampproject/amphtml

✨ Record new tick event fid (first input delay).

 describes.realWin('performance with experiment', {amp: true}, env => {     });   }); });++describes.realWin('performance with firstInput events', {amp: true}, env => {+  describe('should forward firstInput events as a fid tick event', () => {+    it('before performance service registered', () => {+      // Pretend that the EventTiming API exists.+      env.win.PerformanceEventTiming = true;

This property gates whether the EventTiming API is enabled or not. I though to stub it so it is automatically cleaned up after the test, but it looks like Sinon does not support this for non-existent object properties.

ericandrewlewis

comment created time in 3 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 15480a6b07bfb052cb8acf2db124b8fae985071a

Add unit tests for first input delay reporting

view details

push time in 3 months

startedbbbradsmith/NES-ca65-example

started time in 3 months

PR opened ampproject/amphtml

✨ Record new tick event fid (first input delay).

This metric allows tracking the delay that occurs when a user first attempts to interact with a page exposed by the Event Timing API.

I haven't introduced a test for this, and would appreciate some feedback on how I should go about this before I do. Should I use sinon to stub/fake out the PerformanceObserver, and send fake firstInput messages through the faked object?

cc @lannka

+33 -0

0 comment

1 changed file

pr created time in 3 months

push eventericandrewlewis/amphtml

Eric Lewis

commit sha 86c3f16ba0044cc0b931ee831fb3fcf90ede729e

Record new tick event fid (first input delay). This metric allows tracking the delay that occurs when a user first attempts to interact with a page. See https://wicg.github.io/event-timing/

view details

push time in 3 months

more