GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — feat(observable): return this from on, once and off by xh123637 · Pull Request #11617 · NativeScript/NativeScript ConversationFixes #6828
The same change applies to What is the current behavior?
What is the new behavior?All of them return the instance they were called on. Existing code that ignores the return value is unaffected. Tests
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactionsObservable.on, once and off returned void, so listeners could not be chained. They now return the Observable instance, matching the Node EventEmitter API. addEventListener and removeEventListener return this as well, and the typed on/once/off overloads across the core package were updated to match. Fixes NativeScript#6828
|
There was an error while loading. Please reload this page.
|
View your CI Pipeline Execution ↗ for commit 309fbaa
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗ ☁️ Nx Cloud last updated this comment at |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
commit: |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@coderabbitai review |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Action performed
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Walkthrough
Severity of issue fixed: Low Merge Risk:
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Note
Follow-up findings are listed below so you can review them separately from inline comments.
Minor (2)
Minor · Annotate every Viewlistener overload withthis. ·index.d.ts:859
packages/core/ui/core/view/index.d.ts:859
Minor · Functional Correctness · Quick win Annotate every
Viewlistener overload withthis.
View.on('loaded', ...)andView.off(...)currently resolve to declarations with implicitanyreturns. Chained calls can therefore bypassViewtype checking. Add: thisto the generic and event-specificonoverloads and tooff.
Minor · Update the Span declaration. · span.ts:116
packages/core/ui/text-base/span.ts:116
Minor · Maintainability & Code Quality · Low value Update the Span declaration.
Spaninherits the updated signatures, butspan.d.tsis unchanged. Declare the updated listener signatures there.As per coding guidelines, “update the neighboring
.d.tswhenever a public API changes.”
packages/core/ui/core/view/view-common.ts: 1
412-412:Trivial · Maintainability & Code Quality · Quick win Add View gesture chaining tests.
The new tests cover only
Observable. They do not executeViewCommon.addEventListenerorViewCommon.removeEventListenerthrough the gesture branch. A regression toreturn;would therefore pass the current tests while breaking direct gesture calls such asview.addEventListener('tap', handler).removeEventListener('tap', handler).packages/core/data/observable/index.spec.ts: 1
166-170:Trivial · Functional Correctness · Quick win Cover idempotent listener operations.
Add return-value assertions for duplicate registration and removal of an absent event. These paths are not covered by the new tests, so a bare early return could regress the fluent contract unnoticed.
Suggested test additions
it('addEventListener and removeEventListener return the observable', () => { const observable = new Observable(); const handler = () => {}; expect(observable.addEventListener('test', handler)).toBe(observable); + expect(observable.addEventListener('test', handler)).toBe(observable); expect(observable.removeEventListener('test', handler)).toBe(observable); + expect(observable.removeEventListener('missing', handler)).toBe(observable); });
34ee8577-b621-4208-b62c-f8f006ca5745packages/core/data/observable-array/index.tspackages/core/data/observable/index.spec.tspackages/core/data/observable/index.tspackages/core/data/virtual-array/index.tspackages/core/media-query-list/index.tspackages/core/native-window/index.d.tspackages/core/native-window/native-window-common.tspackages/core/native-window/window-base.tspackages/core/ui/action-bar/index.d.tspackages/core/ui/button/index.d.tspackages/core/ui/core/view/index.android.tspackages/core/ui/core/view/index.d.tspackages/core/ui/core/view/view-common.tspackages/core/ui/frame/index.d.tspackages/core/ui/image-cache/image-cache-common.tspackages/core/ui/image-cache/index.d.tspackages/core/ui/list-view/index.d.tspackages/core/ui/list-view/list-view-common.tspackages/core/ui/page/index.d.tspackages/core/ui/page/page-common.tspackages/core/ui/placeholder/index.android.tspackages/core/ui/placeholder/index.d.tspackages/core/ui/placeholder/index.tspackages/core/ui/scroll-view/index.d.tspackages/core/ui/scroll-view/scroll-view-common.tspackages/core/ui/search-bar/index.d.tspackages/core/ui/segmented-bar/index.d.tspackages/core/ui/segmented-bar/segmented-bar-common.tspackages/core/ui/tab-view/index.d.tspackages/core/ui/tab-view/tab-view-common.tspackages/core/ui/text-base/span.tspackages/core/ui/web-view/index.d.tspackages/core/ui/web-view/web-view-common.tsIncluded review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| public on(eventName: string, callback: (data: EventData) => void, thisArg?: any): this { | ||
| this.addEventListener(eventName, callback, thisArg); | ||
|
|
||
| return this; |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Script executed:
rg -n --glob '*.ts' --glob '*.js' '(on|once|off|addEventListener|removeEventListener)\s*\(' packages/core | head -n 220
Repository: NativeScript/NativeScript
Length of output: 25903
Script executed:
git diff --stat 07e84ec588e1103bda0f58bbb37594bf48ccba57 309fbaa167e2b3e49391e7652039118cb30db01a nl -ba packages/core/data/observable/index.ts | sed -n '125,310p' rg -n --glob '*.{ts,js}' '(^|[[:space:]])(public |protected |private |override |static |async )*(on|once|off|addEventListener|removeEventListener)[[:space:]]*\(' packages --glob '!*.spec.ts' --glob '!*.test.ts'
Repository: NativeScript/NativeScript
Length of output: 41344
Script executed:
for f in \ packages/core/data/observable-array/index.ts \ packages/core/data/virtual-array/index.ts \ packages/core/media-query-list/index.ts \ packages/core/native-window/window-base.ts \ packages/core/native-window/native-window-common.ts \ packages/core/ui/core/view/view-common.ts \ packages/core/ui/core/view/index.android.ts \ packages/core/ui/scroll-view/scroll-view-common.ts \ packages/core/ui/text-base/span.ts \ packages/core/ui/shared-transition/shared-transition.ts \ packages/core/ui/transition/shared-transition.ts \ packages/core/ui/image-cache/image-cache-common.ts \ packages/core/ui/page/page-common.ts \ packages/core/ui/web-view/web-view-common.ts \ packages/core/ui/list-view/list-view-common.ts \ packages/core/ui/tab-view/tab-view-common.ts \ packages/core/ui/segmented-bar/segmented-bar-common.ts \ packages/core/ui/placeholder/index.ts \ packages/core/ui/placeholder/index.android.ts; do if test -f "$f"; then echo "===== $f =====" rg -n -C 8 '(^|[[:space:]])(public |protected |private |override |static |async )*(on|once|off|addEventListener|removeEventListener)[[:space:]]*\(' "$f" || true fi done echo "===== class inheritance =====" rg -n --glob '*.ts' 'class [A-Za-z0-9_$]+ extends (Observable|ViewBase|ScrollViewBase|NativeWindow|WindowBase|MediaQueryListImpl|Span)' packages/core || true echo "===== shared transition =====" nl -ba packages/core/ui/transition/shared-transition.ts | sed -n '170,220p'
Repository: NativeScript/NativeScript
Length of output: 29876
Script executed:
for f in \ packages/core/data/observable-array/index.ts \ packages/core/data/virtual-array/index.ts \ packages/core/media-query-list/index.ts \ packages/core/native-window/window-base.ts \ packages/core/native-window/native-window-common.ts \ packages/core/ui/core/view/view-common.ts \ packages/core/ui/core/view/index.android.ts \ packages/core/ui/scroll-view/scroll-view-common.ts \ packages/core/ui/text-base/span.ts \ packages/core/ui/transition/shared-transition.ts \ packages/core/ui/image-cache/image-cache-common.ts \ packages/core/ui/page/page-common.ts \ packages/core/ui/web-view/web-view-common.ts \ packages/core/ui/list-view/list-view-common.ts \ packages/core/ui/tab-view/tab-view-common.ts \ packages/core/ui/segmented-bar/segmented-bar-common.ts \ packages/core/ui/placeholder/index.ts \ packages/core/ui/placeholder/index.android.ts; do if test -f "$f"; then echo "===== $f =====" rg -n -C 8 '(^|[[:space:]])(public |protected |private |override |static |async )*(on|once|off|addEventListener|removeEventListener)[[:space:]]*\(' "$f" || true fi done echo "===== class inheritance =====" rg -n --glob '*.ts' 'class [A-Za-z0-9_$]+ extends (Observable|ViewBase|ScrollViewBase|NativeWindow|WindowBase|MediaQueryListImpl|Span)' packages/core || true echo "===== shared transition =====" nl -ba packages/core/ui/transition/shared-transition.ts | sed -n '170,220p'
Repository: NativeScript/NativeScript
Length of output: 29876
Script executed:
rg -n -C 5 -e 'sharedTransitionEvents' -e 'SharedTransitionObservable' packages/core/ui/transition packages/core rg -n -C 3 -e 'SharedTransition.events' -e 'SharedTransition.get' packages/core apps --glob '*.{ts,js,xml}' || test "$?" -eq 1 nl -ba packages/core/ui/transition/shared-transition.ts | sed -n '215,360p' nl -ba packages/core/ui/core/view/view-common.ts | sed -n '388,455p' nl -ba packages/core/ui/core/view/index.android.ts | sed -n '638,680p' nl -ba packages/core/media-query-list/index.ts | sed -n '110,158p' nl -ba packages/core/ui/scroll-view/scroll-view-common.ts | sed -n '33,68p' git diff 07e84ec588e1103bda0f58bbb37594bf48ccba57 309fbaa167e2b3e49391e7652039118cb30db01a -- packages/core/ui/transition/shared-transition.ts
Repository: NativeScript/NativeScript
Length of output: 44157
Return the receiver from SharedTransitionObservable.on.
SharedTransition.events().on(...) returns undefined because the override discards the superclass result. A JavaScript chain then throws, and TypeScript callers cannot chain through on. Return super.on(eventNames, <any>callback, thisArg) from the override.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
| // @ts-ignore | ||
| public addEventListener(eventName: string, callback: (data: EventData) => void, thisArg?: any, once?: boolean): void { | ||
| public addEventListener(eventName: string, callback: (data: EventData) => void, thisArg?: any, once?: boolean): this { |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Script executed:
sed -n '1,75p' packages/core/media-query-list/index.ts; sed -n '200,360p' packages/core/media-query-list/index.ts; rg -n --glob '*.ts' 'interface MediaQueryList|declare.*MediaQueryList|function matchMedia|matchMedia\s*[:=]' packages/core | head -n 70
Repository: NativeScript/NativeScript
Length of output: 3003
Script executed:
git diff 07e84ec588e1103bda0f58bbb37594bf48ccba57 309fbaa167e2b3e49391e7652039118cb30db01a -- packages/core/media-query-list/index.ts packages/core/native-window/index.d.ts packages/core/native-window/window-base.ts packages/core/native-window/native-window-common.ts nl -ba packages/core/media-query-list/index.ts | sed -n '45,215p' rg -n -F -e 'matchMedia' -e 'MediaQueryList' -- packages/core/native-window packages/core/globals packages/core/media-query-list packages/core/package.json || test "$?" -eq 1 rg --files packages/core/media-query-list
Repository: NativeScript/NativeScript
Length of output: 41775
Script executed:
nl -ba packages/core/globals/index.ts | sed -n '300,340p' rg -n -F -e 'interface MediaQueryList' -e 'declare var matchMedia' -e 'matchMedia(' -e 'MediaQueryList' --glob '*.ts' --glob '*.d.ts' --glob 'tsconfig*.json' . rg -n -F -e '"dom"' -e "'dom'" -e 'lib' --glob 'tsconfig*.json' --glob '*.json' packages/core | head -n 100 find packages/core -maxdepth 3 -type f \( -name '*.d.ts' -o -name 'tsconfig*.json' \) -print
Repository: NativeScript/NativeScript
Length of output: 13555
Script executed:
nl -ba packages/core/tsconfig.lib.json nl -ba tsconfig.base.json | sed -n '1,140p' nl -ba apps/ui/tsconfig.json nl -ba apps/ui/src/media-queries/main-page.ts | sed -n '1,48p' nl -ba packages/core/package.json | sed -n '1,100p' nl -ba packages/core/globals/index.ts | sed -n '1,60p;275,330p' rg -n '"typescript"|typescript@|typescript:' package.json pnpm-lock.yaml yarn.lock package-lock.json 2>/dev/null | head -n 50 command -v tsc TSC="$(command -v tsc)"; if [ -n "$TSC" ]; then ROOT="$(dirname "$(dirname "$(readlink -f "$TSC")")")"; echo "typescript root: $ROOT"; rg -n '^(interface MediaQueryList extends|declare function matchMedia| addEventListener<K extends keyof MediaQueryListEventMap>| removeEventListener<K extends keyof MediaQueryListEventMap>)' "$ROOT/lib/lib.dom.d.ts"; fi
Repository: NativeScript/NativeScript
Length of output: 12930
Web query:
TypeScript 5.9.3 lib.dom.d.ts "declare function matchMedia" "interface MediaQueryList" addEventListener void
Result:
Sources consulted:
- https://raw.githubusercontent.com/microsoft/TypeScript/v5.9.3/lib/lib.dom.d.ts
- https://raw.githubusercontent.com/microsoft/TypeScript/v5.9.3/src/lib/dom.generated.d.ts
- Releases · microsoft/TypeScript · GitHub — https://github.com/microsoft/TypeScript/releases
- …and 26 more
Script executed:
readlink -f /usr/local/bin/tsc ls -l /usr/local/bin/tsc /usr/local/lib/node_modules/typescript 2>&1 nl -ba packages/core/tsconfig.json nl -ba package.json | sed -n '100,115p'
Repository: NativeScript/NativeScript
Length of output: 1702
Script executed:
TSROOT=/usr/local/lib/node_modules/typescript rg -n -F -e 'interface MediaQueryList' -e 'declare function matchMedia' -e 'addEventListener<K extends keyof MediaQueryListEventMap>' -e 'removeEventListener<K extends keyof MediaQueryListEventMap>' "$TSROOT/lib/lib.dom.d.ts" rg -n -F -e 'matchMedia' -e 'MediaQueryList' packages/core/index.ts packages/core/index.d.ts packages/core/global-types.d.ts packages/core/references.d.ts packages/core/typings packages/core 2>/dev/null | head -n 120 nl -ba packages/core/index.ts | sed -n '1,180p' nl -ba packages/core/index.d.ts | sed -n '1,180p' nl -ba packages/core/global-types.d.ts | sed -n '1,160p'
Repository: NativeScript/NativeScript
Length of output: 21053
Web query:
site:raw.githubusercontent.com/microsoft/TypeScript/v5.9.3/lib/lib.dom.d.ts "interface MediaQueryList" "addEventListener" "removeEventListener"
Result:
Sources consulted:
- https://raw.githubusercontent.com/microsoft/TypeScript/v5.9.3/lib/lib.dom.d.ts
Expose fluent listener types for the global matchMedia API.
tsconfig.base.json includes the DOM declarations, where MediaQueryList.addEventListener and removeEventListener return void. NativeScript does not augment these declarations, so chaining global matchMedia(...).addEventListener(...) still fails type-checking despite the runtime implementation returning this.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
Observable 'on' and 'off' should return 'this'
There was an error while loading. Please reload this page.