Prepack: "all native function values should be intrinsics" - what does it mean?

Created on 20 Dec 2017  路  9Comments  路  Source: facebook/prepack

I am trying to run prepack on an existing code, I get this error

all native function values should be intrinsics
Invariant Violation: all native function values should be intrinsics

It doesn't show me where exactly is the error in the code, so I am asking here. What does it mean, and how can I find where the error comes from?

bug help wanted

All 9 comments

An invariant violation means that something that we thought is impossible has actually happened. I.e. you've run into a programming bug and the onus is on the Prepack developers to fix the problem.

As always, if there is a simple way to reproduce this failure it will be a great help to the developers and speed up the resolution of this problem.

Oh OK! I will try to make a minimal case

I just ran into this too. It's very difficult to reduce down to a test case given the nature of running prepack on a generated bundle. My bundle isn't too big, it's ~1500 lines, and here it is: https://gist.github.com/jlongster/85c2f8f313bf52af1e7996b285273587

FWIW here's the screenshot of the error:

screen shot 2018-01-02 at 11 55 57 am

Any tips for how to make a reduced test case? If you hit this yourself how would you do it? I suppose I can try to invoke smaller parts of the system and see what happens.

I figured it out - it's promises. How well are promises supported?

I install a global function in my VM which returns a promise: https://gist.github.com/jlongster/85c2f8f313bf52af1e7996b285273587#file-interpreter-output-js-L257-L263. This function is available to the code my VM is interpreting.

At the point where my VM implements the CALL operator which calls functions, it checks the return type to see if it's a promise, and if so, it suspends the VM: https://gist.github.com/jlongster/85c2f8f313bf52af1e7996b285273587#file-interpreter-output-js-L348-L350

If I remove these two pieces of code (make foo return a normal value, and don't check the return type) prepack successfully evaluates my VM.

Maybe this issue is known and promises aren't well-supported yet.

Evaluating Promises should work but there might be bugs in the serializer, which this looks like it might be.

It is likely that Promises needs to be serialized using a special case branch here since they have to use a built-in constructor (similar to Date). https://github.com/facebook/prepack/blob/master/src/serializer/ResidualHeapSerializer.js#L1204-L1268

Here's a small repro:

global.d = Object.getOwnPropertyDescriptor(Map.prototype, "size");

I'm currently working on this, fixing native properties (such as Map.prototype.size). I assume promises are handled by #1306.

Actually, prepack should not (?) replace getOwnPropertyDescriptor call for native accessors because there is no way to access native getter/setter functions without a call to getOwnPropertyDescriptor or to its variants.
For the example given above, output could be something like:

(function () {
  var _0 = Object.getOwnPropertyDescriptor(Map.prototype, "size");
  d = _0;
}).call(this);

After making isIntrinsic() return true for Map.prototype#size, current output is as follows which is obviously wrong:

(function () {
  var _$0 = this;

  var _$1 = _$0.Map;
  var _$2 = _$1.prototype;
  var _$3 = _$2.size; // Because I've set getter fn's intrinsic name to Map.prototype.size for now.
  var _4 = _$3;
  var _0 = {
    get: _4,
    set: void 0,
    enumerable: false,
    configurable: true
  };
  d = _0;
}).call(this);

Setting intrinsicName for native accessor functions to the following fixes this bug: `Object.getOwnPropertyDescriptor(${this.intrinsicName}, "${name}").${accessorType}` where accessorType: "get" | "set".

This produces non-optimal code. E.g:

Input:

(function() {
    var desc = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__');
    global.g = desc.get;
    global.s = desc.set;
    global.c = desc.configurable;
})();

Output:

(function () {
  var _$0 = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").get;
  var _$1 = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set;
  var _2 = _$0;
  g = _2;
  var _1 = _$1;
  s = _1;
  c = true;
})();

I'm pretty sure there's a better approach but I cannot unearth it.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NTillmann picture NTillmann  路  3Comments

maxime1992 picture maxime1992  路  5Comments

gaearon picture gaearon  路  5Comments

phpnode picture phpnode  路  3Comments

skyne98 picture skyne98  路  7Comments