Skip to content

fix(core): restore the per-side padding setNative protocol - #11368

Merged
NathanWalker merged 2 commits into
mainfrom
fix/padding-setnative-protocol
Aug 27, 2026
Merged

fix(core): restore the per-side padding setNative protocol#11368
NathanWalker merged 2 commits into
mainfrom
fix/padding-setnative-protocol

Conversation

@edusperoni

@edusperoni edusperoni commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

PR Checklist

What is the current behavior?

#11216 consolidated padding application into an internal paddingInternal property and deleted the per-side [padding*Property.setNative] / [padding*Property.getDefault] handlers from Button (iOS + Android), Label (iOS), LayoutBase (Android), TextBase (Android), TextField (iOS) and TextView (iOS).

Those per-property native handlers are the de-facto public extension surface every plugin builds on. Two breakages for subclasses (e.g. @nativescript-community/ui-label):

  1. Crash — an override that chains to the base implementation now throws, because the base handler no longer exists:
    [paddingTopProperty.setNative](value) {
        if (!this.isUsingNSTextView) {
            super[paddingTopProperty.setNative](value); // TypeError: … is not a function
        }
    }
    TypeError: (intermediate value)[paddingLeftProperty.setNative] is not a function
        at applyAllNativeSetters (ui/core/properties/index.js)
        at initNativeView …
    
  2. Silent bypass — an override whose purpose is to suppress core's padding application no longer suppresses anything: core applies padding through paddingInternal, around the per-side protocol.

What is the new behavior?

The per-side handlers are restored on all six classes, restructured so #11216's one-native-write goal still holds:

  • Each [padding*Property.setNative] stages its side into a pending insets struct (using the same effective-value computations the consolidated handler used).
  • [paddingInternalProperty.setNative] seeds the struct from the current native padding, drives the four per-side handlers — subclass overrides included — and commits a single native write.
  • A side whose override does not chain to super keeps its current native value, which is exactly what suppression produced before perf(core): reduce padding native setter calls #11216.
  • getDefault handlers return the same values they did before.
  • Standalone invocations of a per-side handler are no-ops; every padding change also updates paddingInternal, which performs the flush.

So: super[padding*Property.setNative] resolves again (no crash), override semantics work again, and padding is still applied in one native call per update.

New regression spec (padding-native-protocol.spec.ts): asserts the handlers exist on the affected prototypes and exercises the exact plugin pattern — a subclass handler chaining to super — without throwing. 426 unit tests passing, core:build clean for both platforms.


Update (d333b1821): the consolidated write now stands down entirely when a subclass overrides any per-side handler (detected once per constructor). In that case the property machinery drives the per-side handlers directly, each applying its own side — full pre-#11216 semantics:

  • suppress: an override that doesn't chain to super means core never touches the native padding for that side (not even a rewrite of the current value — important when the plugin redirects padding to a different native mechanism);
  • transform: super[padding*Property.setNative](differentValue) applies the transformed value on Android, which honors the value argument again exactly like the old handlers (iOS handlers keep reading effective values, as they always did);
  • chain: plain super chaining applies the side normally.

Views with no overrides keep the staged single-native-write path. The spec now covers all of the above against a stubbed native view.

Consolidating padding into paddingInternal (#11216) deleted the
[padding*Property.setNative] and [padding*Property.getDefault] handlers
from Button, Label, LayoutBase, TextBase, TextField and TextView. The
per-property native handlers are the extension surface plugins build on:
a subclass that overrides one and chains with
super[paddingTopProperty.setNative](value) now throws, and one that
overrides to suppress core's padding application is silently bypassed,
since padding flows through paddingInternal around it.

The handlers are back, restructured so the single-native-write goal of
the consolidation still holds: each per-side handler stages its side
into a pending struct, and [paddingInternalProperty.setNative] seeds
that struct from the current native padding, drives the four per-side
handlers - subclass overrides included - and commits one native write.
A side whose override does not chain to super keeps its current native
value, which is what suppression looked like before. The getDefault
handlers return the same values they used to.

Standalone invocations of a per-side handler are no-ops: every padding
change also updates paddingInternal, which performs the flush.
@nx-cloud

nx-cloud Bot commented Aug 26, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit d333b18

Command Status Duration Result
nx test apps-automated -c=ios ✅ Succeeded 1m 52s View ↗
nx run-many --target=test --configuration=ci --... ✅ Succeeded 1s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-08-27 00:18:57 UTC

@pkg-pr-new

pkg-pr-new Bot commented Aug 26, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@nativescript/core@11368
npm i https://pkg.pr.new/@nativescript/vite@11368
npm i https://pkg.pr.new/@nativescript/webpack@11368

commit: d333b18

An override of a per-side [padding*Property.setNative] handler exists to
intercept padding application - suppress it, transform the value, or
redirect it to a different native mechanism. The consolidated
paddingInternal write applied padding around such overrides, so the
interception never mattered.

When a subclass overrides any of the four handlers (detected once per
constructor), the consolidated write now stands down and the property
machinery drives the per-side handlers directly, each applying its own
side - the pre-consolidation behavior, including not touching the native
view at all for a suppressed side. Without overrides the staged
single-write path is unchanged.

The android handlers also honor the value argument again instead of
reading the effective value, so chaining super with a transformed value
applies that value - as it did before the consolidation. The ios
handlers keep reading effective values, which is what they always did.
@NathanWalker
NathanWalker merged commit 93a59db into main Aug 27, 2026
10 of 11 checks passed
@NathanWalker
NathanWalker deleted the fix/padding-setnative-protocol branch August 27, 2026 01:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants