NativeScript / canvas

Apache License 2.0
88 stars 18 forks source link

NPE: Parameter specified as non-null is null: method #95

Closed CatchABus closed 8 months ago

CatchABus commented 1 year ago

It seems canvas 2D doesn't handle null values like browser. In my case, I use a plugin that sets value to shadowColor even if that value is null.

In browser, null assignments are usually ignored but {N} canvas throws exception:

System.err: An uncaught Exception occurred on "main" thread.
  System.err: Calling js method run failed
  System.err: Error: java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter color
  System.err:
  System.err: StackTrace:
  System.err: set shadowColor(file: node_modules/@nativescript/canvas/Canvas2D/CanvasRenderingContext2D/index.android.js:103:0)
  System.err:   at D(file: node_modules/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.min.js:7:3125)
  System.err:   at draw(file: node_modules/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.min.js:7:14457)
  System.err:   at Ct(file: node_modules/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.min.js:7:28761)
  System.err:   at afterDatasetsDraw(file: node_modules/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.min.js:7:27710)
  System.err:   at callback(file: node_modules/chart.js/dist/chunks/helpers.segment.mjs:47:0)
  System.err:   at _notify(file: node_modules/chart.js/dist/chart.mjs:4988:18)
  System.err:   at notify(file: node_modules/chart.js/dist/chart.mjs:4975:0)
  System.err:   at notifyPlugins(file: node_modules/chart.js/dist/chart.mjs:6124:0)
  System.err:   at _drawDatasets(file: node_modules/chart.js/dist/chart.mjs:5871:0)
  System.err:   at draw(file: node_modules/chart.js/dist/chart.mjs:5842:0)
  System.err:   at render(file: node_modules/chart.js/dist/chart.mjs:5820:0)
  System.err:   at update(file: node_modules/chart.js/dist/chart.mjs:5719:0)
  System.err:   at Chart(file: node_modules/chart.js/dist/chart.mjs:5476:0)
  System.err:   at (file: app/views/assetDetails/assetDetails.js:237:0)
  System.err:   at _handleEvent(file: node_modules/@nativescript/core/data/observable/index.js:235:0)
  System.err:   at notify(file: node_modules/@nativescript/core/data/observable/index.js:216:0)
  System.err:   at onNavigatedTo(file: node_modules/@nativescript/core/ui/page/page-common.js:93:0)
  System.err:   at setCurrent(file: node_modules/@nativescript/core/ui/frame/frame-common.js:211:0)
  System.err:   at setCurrent(file: node_modules/@nativescript/core/ui/frame/index.android.js:292:0)
  System.err:   at (file: node_modules/@nativescript/core/ui/frame/fragment.transitions.android.js:559:0)
  System.err:   at invoke(file: node_modules/@nativescript/core/timer/index.android.js:22:0)
  System.err:   at run(file: node_modules/@nativescript/core/timer/index.android.js:26:0)
  System.err:   at com.tns.Runtime.callJSMethodNative(Native Method)
  System.err:   at com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1302)
  System.err:   at com.tns.Runtime.callJSMethodImpl(Runtime.java:1188)
  System.err:   at com.tns.Runtime.callJSMethod(Runtime.java:1175)
  System.err:   at com.tns.Runtime.callJSMethod(Runtime.java:1153)
  System.err:   at com.tns.Runtime.callJSMethod(Runtime.java:1149)
  System.err:   at com.tns.gen.java.lang.Runnable.run(Runnable.java:17)
  System.err:   at android.os.Handler.handleCallback(Handler.java:938)
  System.err:   at android.os.Handler.dispatchMessage(Handler.java:99)
  System.err:   at android.os.Looper.loop(Looper.java:236)
  System.err:   at android.app.ActivityThread.main(ActivityThread.java:8057)
  System.err:   at java.lang.reflect.Method.invoke(Native Method)
  System.err:   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620)
  System.err:   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011)
  System.err: Caused by: java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter color
  System.err:   at org.nativescript.canvas.TNSCanvasRenderingContext2D.setShadowColor(Unknown Source:2)
  System.err:   ... 14 more

How plugin setters work now:

    set arandomconvasprop(val) {
        this.log('arandomconvasprop value:', val);
        this._ensureLayoutBeforeDraw();
        if (this.context) {
            this.context.setArandomconvasprop(val);
        }
    }

How they actually behave in browser:

    set arandomconvasprop(val) {
        this.log('arandomconvasprop value:', val);

        if (color == null) {
            return;
        }

        this._ensureLayoutBeforeDraw();
        if (this.context) {
            this.context.setArandomconvasprop(val);
        }
    }

A sample with shadowColor to confirm this: https://jsfiddle.net/k8ums9ra/

CatchABus commented 1 year ago

In the case of properties or methods that accept string values like measureText in browser environment, non-string values will be converted to string. A call of ctx.measureText(null).width will return 46.69921875 as null gets treated as "null". {N} canvas throws NPEs for those too though.

triniwiz commented 8 months ago

Fixed in v2