Victory-native: [Minification Bug] Line Chart Crashes when minified

Created on 2 Dec 2017  Â·  17Comments  Â·  Source: FormidableLabs/victory-native

I have a pretty basic line chart. When I render it in debug / production mode (doesn't matter which) UNMINIFIED, it renders properly:

screenshot_20171201-210507

But when I render it in debug / production with MINIFIED code, I get a cryptic error:

screenshot_20171201-210153

Because this error only happens on minified code, I'm not even sure how to begin debugging this. Thoughts?

Versions:

    "react-native-svg": "6.0.0",
    "victory": "0.24.2",
    "victory-native": "0.16.1"
bug duplicate unverified

Most helpful comment

Alright, so for some reason, the constants in this method are not being defined properly when React Native tries to minify it. You can trick React Native into defining them by invoking them in the method (e.g. immediately with the Log function). This "works":

    const axisOrientations = {
      x: Axis.getOrientation(axisComponents.x, "x", originSign.y),
      y: Axis.getOrientation(axisComponents.y, "y", originSign.x)
    };
    Log.warn(axisOrientations); // added this
    const orientationOffset = {
      y: axisOrientations.x === "bottom" ? bottom : top,
      x: axisOrientations.y === "left" ? left : right
    };
    Log.warn(orientationOffset); // added this
    const originOffset = {
      x: axisOrientations.y === "left" ? 0 : props.width,
      y: axisOrientations.x === "bottom" ? props.height : 0
    };
    Log.warn(originOffset); // added this
    const originPosition = {
      x: origin.x === domain.x[0] || origin.x === domain.x[1] ? 0 : scale.x(origin.x),
      y: origin.y === domain.y[0] || origin.y === domain.y[1] ? 0 : scale.y(origin.y)
    };
    Log.warn(originPosition); // added this
    const calculatedOffset = {
      x: originPosition.x ? Math.abs(originOffset.x - originPosition.x) : orientationOffset.x,
      y: originPosition.y ? Math.abs(originOffset.y - originPosition.y) : orientationOffset.y
    };
    Log.warn(calculatedOffset); // added this

This is a terrible workaround, but I'm out of other ideas.

[email protected]

All 17 comments

Looking at the minified bundle and doing lots of digging, I'm able to trace this back to:

https://github.com/FormidableLabs/victory-chart/blob/b0cfdb55d5f8cb8610164effef74aa33bbe3f077/src/components/victory-chart/helper-methods.js#L78

When this code is minified in react native, the axisOrientations variable is NOT set, but is called upon, causing this error.

Alright, so for some reason, the constants in this method are not being defined properly when React Native tries to minify it. You can trick React Native into defining them by invoking them in the method (e.g. immediately with the Log function). This "works":

    const axisOrientations = {
      x: Axis.getOrientation(axisComponents.x, "x", originSign.y),
      y: Axis.getOrientation(axisComponents.y, "y", originSign.x)
    };
    Log.warn(axisOrientations); // added this
    const orientationOffset = {
      y: axisOrientations.x === "bottom" ? bottom : top,
      x: axisOrientations.y === "left" ? left : right
    };
    Log.warn(orientationOffset); // added this
    const originOffset = {
      x: axisOrientations.y === "left" ? 0 : props.width,
      y: axisOrientations.x === "bottom" ? props.height : 0
    };
    Log.warn(originOffset); // added this
    const originPosition = {
      x: origin.x === domain.x[0] || origin.x === domain.x[1] ? 0 : scale.x(origin.x),
      y: origin.y === domain.y[0] || origin.y === domain.y[1] ? 0 : scale.y(origin.y)
    };
    Log.warn(originPosition); // added this
    const calculatedOffset = {
      x: originPosition.x ? Math.abs(originOffset.x - originPosition.x) : orientationOffset.x,
      y: originPosition.y ? Math.abs(originOffset.y - originPosition.y) : orientationOffset.y
    };
    Log.warn(calculatedOffset); // added this

This is a terrible workaround, but I'm out of other ideas.

[email protected]

I have a similar problem but @joncursi solution didn't work for me, I have this code:

        <VictoryChart theme={VictoryTheme.material} domainPadding={10}>
          <VictoryBar
            style={{ data: { fill: "#c43a31" } }}
            data={this.state.data}
          />
        </VictoryChart>

Im only using on iOS is working on emulator with: react-native run-ios, but in Xcode its trowing this error:
2017-12-04 19:15:28.894584-0600 MyProject[20890:11945717] ReferenceError: Can't find variable: a2637
This error is located at:
in VictoryChart
in RCTView
in RCTView
in RCTScrollContentView
in RCTScrollView
in ScrollView
in KeyboardAwareScrollView
in t
in Styled(t)
in RCTView
in t
in Styled(t)
in t
in Connect(t)
in n
in t
in RCTView
in n
in t
in n
...etc..
If I remove VictoryChart it works, but in my case I want to use VictoryChart.

Did you find any solution?

No solution yet. Hoping for a package dev to chime in and provide suggestions. I'm stumped on this one.

Same here, waiting for a solution.
i think this issue is the same problem
https://github.com/FormidableLabs/victory-native/issues/199

@joncursi's method works for me, but it the warning notification annoys me quite a lot on debug mode. So, shall anyone encounter the same issue, I modified the code a bit so it's less annoying but still works.

  const axisOrientations = {
      x: Axis.getOrientation(axisComponents.x, "x", originSign.y),
      y: Axis.getOrientation(axisComponents.y, "y", originSign.x)
    };
    axisOrientations; // added this
    const orientationOffset = {
      y: axisOrientations.x === "bottom" ? bottom : top,
      x: axisOrientations.y === "left" ? left : right
    };
    orientationOffset; // added this
    const originOffset = {
      x: axisOrientations.y === "left" ? 0 : props.width,
      y: axisOrientations.x === "bottom" ? props.height : 0
    };
    originOffset; // added this
    const originPosition = {
      x: origin.x === domain.x[0] || origin.x === domain.x[1] ? 0 : scale.x(origin.x),
      y: origin.y === domain.y[0] || origin.y === domain.y[1] ? 0 : scale.y(origin.y)
    };
    originPosition; // added this
    const calculatedOffset = {
      x: originPosition.x ? Math.abs(originOffset.x - originPosition.x) : orientationOffset.x,
      y: originPosition.y ? Math.abs(originOffset.y - originPosition.y) : orientationOffset.y
    };
    calculatedOffset; // added this

@athirah-yahya @joncursi -- Thanks. As an update, I'm manually minifying and unpacking things to see if I can understand more what's happening to that function...

And we're confident it's the variable axisOrientations that is no longer defined as the first-level exception being thrown?

All of the constants are not being properly defined in that function, for
whatever reason. That’s why we’re dropping in those few lines. If we only
invoke axisOrientations, then it will fail on orientationOffset. They all
need to be invoked to prevent the issue
On Wed, Dec 20, 2017 at 11:33 PM Ryan Roemer notifications@github.com
wrote:

@athirah-yahya https://github.com/athirah-yahya @joncursi
https://github.com/joncursi -- Thanks. As an update, I'm manually
minifying and unpacking things to see if I can understand more what's
happening to that function...

And we're confident it's the variable axisOrientations that is no longer
defined as the first-level exception being thrown?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/FormidableLabs/victory-native/issues/197#issuecomment-353256037,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AEvoEYTrMlkcdBrVE2fJPhtZ50NTM9Mtks5tCd-dgaJpZM4QzII1
.

So here's our starting raw source:

  // eslint-disable-next-line complexity
  getAxisOffset(props, calculatedProps) {
    const { axisComponents, scale, origin, domain, originSign, padding } = calculatedProps;
    const { top, bottom, left, right } = padding;
    // make the axes line up, and cross when appropriate
    const axisOrientations = {
      x: Axis.getOrientation(axisComponents.x, "x", originSign.y),
      y: Axis.getOrientation(axisComponents.y, "y", originSign.x)
    };
    const orientationOffset = {
      y: axisOrientations.x === "bottom" ? bottom : top,
      x: axisOrientations.y === "left" ? left : right
    };
    const originOffset = {
      x: axisOrientations.y === "left" ? 0 : props.width,
      y: axisOrientations.x === "bottom" ? props.height : 0
    };
    const originPosition = {
      x: origin.x === domain.x[0] || origin.x === domain.x[1] ? 0 : scale.x(origin.x),
      y: origin.y === domain.y[0] || origin.y === domain.y[1] ? 0 : scale.y(origin.y)
    };
    const calculatedOffset = {
      x: originPosition.x ? Math.abs(originOffset.x - originPosition.x) : orientationOffset.x,
      y: originPosition.y ? Math.abs(originOffset.y - originPosition.y) : orientationOffset.y
    };

    return {
      x: axisComponents.x && axisComponents.x.offsetX !== undefined ?
        axisComponents.x.offsetX : calculatedOffset.x,
      y: axisComponents.y && axisComponents.y.offsetY !== undefined ?
        axisComponents.y.offsetY : calculatedOffset.y
    };
  },

Minified, and then prettified:

getAxisOffset: function(e, t) {
  var n = t.axisComponents,
    r = t.scale,
    i = t.origin,
    a = t.domain,
    d = t.originSign,
    l = t.padding,
    p = l.top,
    u = l.bottom,
    f = l.left,
    s = l.right,
    c = o.default.getOrientation(n.x, "x", d.y),
    g = o.default.getOrientation(n.y, "y", d.x),
    y = {
      y: "bottom" === c ? u : p,
      x: "left" === g ? f : s
    },
    h = "left" === g ? 0 : e.width,
    x = "bottom" === c ? e.height : 0,
    m = i.x === a.x[0] || i.x === a.x[1] ? 0 : r.x(i.x),
    b = i.y === a.y[0] || i.y === a.y[1] ? 0 : r.y(i.y),
    v = {
      x: m ? Math.abs(h - m) : y.x,
      y: b ? Math.abs(x - b) : y.y
    };
  return {
    x: n.x && void 0 !== n.x.offsetX ? n.x.offsetX : v.x,
    y: n.y && void 0 !== n.y.offsetY ? n.y.offsetY : v.y
  }
},

Manually unpacking with original variable names:

getAxisOffset: function(props, calculatedProps) {
  var axisComponents = calculatedProps.axisComponents,
    scale = calculatedProps.scale,
    origin = calculatedProps.origin,
    domain = calculatedProps.domain,
    originSign = calculatedProps.originSign,
    padding = calculatedProps.padding,

    top = padding.top,
    bottom = padding.bottom,
    left = padding.left,
    right = padding.right,

    // Axis = o.default
    axisOrientations_x = o.default.getOrientation(axisComponents.x, "x", originSign.y),
    axisOrientations_y = o.default.getOrientation(axisComponents.y, "y", originSign.x),

    orientationOffset = {
      y: "bottom" === axisOrientations_x ? bottom : top,
      x: "left" === axisOrientations_y ? left : right
    },

    originOffset_x = "left" === axisOrientations_y ? 0 : props.width,
    originOffset_y = "bottom" === axisOrientations_x ? props.height : 0,

    originPosition_x = origin.x === domain.x[0] || origin.x === domain.x[1] ? 0 : scale.x(origin.x),
    originPosition_y = origin.y === domain.y[0] || origin.y === domain.y[1] ? 0 : scale.y(origin.y),

    calculatedOffset = {
      x: originPosition_x ? Math.abs(originOffset_x - originPosition_x) : orientationOffset.x,
      y: originPosition_y ? Math.abs(originOffset_y - originPosition_y) : orientationOffset.y
    };

  return {
    x: axisComponents.x && void 0 !== axisComponents.x.offsetX ? axisComponents.x.offsetX : calculatedOffset.x,
    y: axisComponents.y && void 0 !== axisComponents.y.offsetY ? axisComponents.y.offsetY : calculatedOffset.y
  }
},

Offhand, that minified code after unpacking _looks_ ok. I'll dive in more today on it.

@athirah-yahya @joncursi -- Can you paste in a comment here or a link to a gist the original minified code for just the getAxisOffset function in your production bundles so I can unpack it and compare? (without the extra variables -- I want the code that breaks). Thanks!

@boygirl -- My hunch is without understanding the underlying bug it may go away if we refactor the pattern:

const coolName = {
  x,
  y
};

to:

const coolNameX;
const coolNameY;

... but I'm going to continue researching here because from first appearances it seem as if the minifier is doing something horribly wrong that could impact us elsewhere...

I think I'm facing the same thing
image

@robophil - Can you paste in a comment here or a link to a gist the original minified code for just the getAxisOffset function in your production bundle?

I'm also facing this issue, any solution?

Or is there a working version that I can downgrade to?

@jswxwxf - Can you paste in a comment here or a link to a gist the original minified code for just the getAxisOffset function (or whatever function is originating the crash) in your production bundle?

Or, if possible, create a minimal repository with install + error reproduction steps to produce the crash?

Unfortunately, there's unlikely to be any real progress on this issue until the core victory-native engineers can see directly what seems to be the problem.

Closing as duplicate of #199 which we're going to track further progress on here. For followers of this thread, read:

Let's have any further updates, research, commenting on that issue. Thanks!

/cc @boygirl

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xkawi picture xkawi  Â·  4Comments

yvonne6344 picture yvonne6344  Â·  4Comments

udfalkso picture udfalkso  Â·  4Comments

ericschaal picture ericschaal  Â·  4Comments

safaiyeh picture safaiyeh  Â·  6Comments