Skip to content

Instantly share code, notes, and snippets.

@calebmer

calebmer/01.md Secret

Last active July 18, 2018 20:02
Show Gist options
  • Save calebmer/1ac381096a4aa7be1fc7dc2163276ab4 to your computer and use it in GitHub Desktop.
Save calebmer/1ac381096a4aa7be1fc7dc2163276ab4 to your computer and use it in GitHub Desktop.
Prepack Serializer Bugs Revealed by test262

The Map value is serialized, but not visited.

I’ve seen other invariant violations of this nature. For instance class O extends Object {}.

Input

class M extends Map {}

var map = new M([{ foo: "bar" }]);

map.set("bar", "baz");

Error

=== serialized but not visited values
=== visited but not serialized values
[object], hash: 1, intrinsic name: Map
  referenced by 1 scopes
      =>main(#0)

Invariant Violation: serialized 6 of 7
debug-fb-www.js:207
This is likely a bug in Prepack, not your code. Feel free to open an issue on GitHub.

Input

class C {
  get p() {}
}

Output

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

  var _0 = class {
    get p() {}

  };

  _0.prototype.p = void 0; // <-------------- `p` is already declared to have a getter! Throws when we try to set.
  _$0.C = _0;
}).call(this);

Input

var Cv = class C {
  constructor() {
    console.log(C === Cv);
  }
};

Output

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

  var _0 = class {
    constructor() {
      console.log(C === Cv); // <------------ References `C`, but there is no class named `C`!
    }
  };

  _$0.Cv = _0;
}.call(this));

Input

class A {
  static get m() {}
}

Error

=== Diagnostics Log ===

Error: PP0022: a class method incorrectly went through the serializeValue() code path at 2:17 to 2:19

=== Compilation Failed ===

Error: A fatal error occurred while prepacking.
    at ResidualHeapSerializer.serializeValue (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:868:15)
    at ResidualHeapSerializer.emitDefinePropertyBody (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:506:109)
    at ResidualHeapSerializer._emitProperty (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:430:30)
    at emitter.emitNowOrAfterWaitingForDependencies (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:218:14)
    at Emitter.emitAfterWaiting (/Users/calebmer/prepack/lib/serializer/Emitter.js:435:9)
    at Emitter.emitNowOrAfterWaitingForDependencies (/Users/calebmer/prepack/lib/serializer/Emitter.js:492:10)
    at ResidualHeapSerializer._emitObjectProperties (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:215:20)
    at ResidualHeapSerializer._serializeClass (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:1360:10)
    at ResidualHeapSerializer._serializeValueFunction (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:1255:14)
    at ResidualHeapSerializer._serializeValueObjectBase (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:1744:18)
    at ResidualHeapSerializer._serializeValue (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:1700:19)
    at ResidualHeapSerializer.serializeValue (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:891:21)
    at nodes.args.map (/Users/calebmer/prepack/lib/utils/generator.js:126:58)
    at Array.map (<anonymous>)
    at TemporalBuildNodeEntry.serialize (/Users/calebmer/prepack/lib/utils/generator.js:126:29)
    at serializeFn (/Users/calebmer/prepack/lib/utils/generator.js:871:46)
    at Generator.serialize (/Users/calebmer/prepack/lib/utils/generator.js:880:7)
    at ResidualHeapSerializer.serialize (/Users/calebmer/prepack/lib/serializer/ResidualHeapSerializer.js:2001:20)
    at statistics.referenceCounts.measure (/Users/calebmer/prepack/lib/serializer/serializer.js:220:654)
    at PerformanceTracker.measure (/Users/calebmer/prepack/lib/statistics.js:91:14)
    at ast (/Users/calebmer/prepack/lib/serializer/serializer.js:219:38)
    at statistics.total.measure (/Users/calebmer/prepack/lib/serializer/serializer.js:230:9)
    at PerformanceTracker.measure (/Users/calebmer/prepack/lib/statistics.js:91:14)
    at Serializer.init (/Users/calebmer/prepack/lib/serializer/serializer.js:148:35)
    at prepackSources (/Users/calebmer/prepack/lib/prepack-standalone.js:71:33)
    at compileSource (/Users/calebmer/prepack/scripts/debug-fb-www.js:92:18)
    at compileFile (/Users/calebmer/prepack/scripts/debug-fb-www.js:129:31)
    at <anonymous>

Input

var date = new Date();
x = date + date;

…or:

x = typeof Date() === "string";

Error

=== Diagnostics Log ===

Error: PP0001: This operation is not yet supported on abstract value   at 2:11 to 2:15

=== Compilation Failed ===

Error: A fatal error occurred while prepacking.
    at AbstractValue.throwIfNotConcreteNumber (/Users/calebmer/prepack/lib/values/AbstractValue.js:506:11)
    at NativeFunctionValue.obj.defineNativeMethod.context [as callback] (/Users/calebmer/prepack/lib/intrinsics/ecma262/DatePrototype.js:574:49)
    at NativeFunctionValue.callCallback (/Users/calebmer/prepack/lib/values/NativeFunctionValue.js:85:51)
    at functionCall (/Users/calebmer/prepack/lib/methods/call.js:250:26)
    at callNativeFunctionValue (/Users/calebmer/prepack/lib/methods/call.js:276:10)
    at OrdinaryCallEvaluateBody (/Users/calebmer/prepack/lib/methods/call.js:282:12)
    at InternalCall (/Users/calebmer/prepack/lib/methods/function.js:80:49)
    at FunctionImplementation.$Call (/Users/calebmer/prepack/lib/methods/function.js:751:12)
    at NativeFunctionValue.$Call (/Users/calebmer/prepack/lib/values/NativeFunctionValue.js:25:36)
    at Call (/Users/calebmer/prepack/lib/methods/call.js:505:12)
    at ToImplementation.OrdinaryToPrimitiveOrAbstract (/Users/calebmer/prepack/lib/methods/to.js:587:37)
    at ToImplementation.OrdinaryToPrimitive (/Users/calebmer/prepack/lib/methods/to.js:561:17)
    at NativeFunctionValue.obj.defineNativeMethod [as callback] (/Users/calebmer/prepack/lib/intrinsics/ecma262/DatePrototype.js:619:27)
    at NativeFunctionValue.callCallback (/Users/calebmer/prepack/lib/values/NativeFunctionValue.js:85:51)
    at functionCall (/Users/calebmer/prepack/lib/methods/call.js:250:26)
    at callNativeFunctionValue (/Users/calebmer/prepack/lib/methods/call.js:276:10)
    at OrdinaryCallEvaluateBody (/Users/calebmer/prepack/lib/methods/call.js:282:12)
    at InternalCall (/Users/calebmer/prepack/lib/methods/function.js:80:49)
    at FunctionImplementation.$Call (/Users/calebmer/prepack/lib/methods/function.js:751:12)
    at NativeFunctionValue.$Call (/Users/calebmer/prepack/lib/values/NativeFunctionValue.js:25:36)
    at Call (/Users/calebmer/prepack/lib/methods/call.js:505:12)
    at ToImplementation.ToPrimitiveOrAbstract (/Users/calebmer/prepack/lib/methods/to.js:530:35)
    at Function.computeBinary (/Users/calebmer/prepack/lib/domains/ValuesDomain.js:128:34)
    at compute (/Users/calebmer/prepack/lib/evaluators/BinaryExpression.js:160:42)
    at computeBinary (/Users/calebmer/prepack/lib/evaluators/BinaryExpression.js:228:10)
    at _default (/Users/calebmer/prepack/lib/evaluators/BinaryExpression.js:49:10)
    at LexicalEnvironment.evaluateAbstract (/Users/calebmer/prepack/lib/environment.js:1185:20)
    at LexicalEnvironment.evaluate (/Users/calebmer/prepack/lib/environment.js:1173:20)
    at _default (/Users/calebmer/prepack/lib/evaluators/AssignmentExpression.js:48:22)
    at LexicalEnvironment.evaluateAbstract (/Users/calebmer/prepack/lib/environment.js:1185:20)
    at LexicalEnvironment.evaluate (/Users/calebmer/prepack/lib/environment.js:1173:20)
    at _default (/Users/calebmer/prepack/lib/evaluators/ExpressionStatement.js:23:21)
    at LexicalEnvironment.evaluateAbstract (/Users/calebmer/prepack/lib/environment.js:1185:20)
    at LexicalEnvironment.evaluate (/Users/calebmer/prepack/lib/environment.js:1173:20)
    at LexicalEnvironment.evaluateCompletion (/Users/calebmer/prepack/lib/environment.js:942:19)
    at LexicalEnvironment.evaluateCompletionDeref (/Users/calebmer/prepack/lib/environment.js:935:23)
    at _default (/Users/calebmer/prepack/lib/evaluators/Program.js:205:21)
    at LexicalEnvironment.evaluateAbstract (/Users/calebmer/prepack/lib/environment.js:1185:20)
    at LexicalEnvironment.evaluate (/Users/calebmer/prepack/lib/environment.js:1173:20)
    at _default (/Users/calebmer/prepack/lib/evaluators/File.js:25:15)
    at LexicalEnvironment.evaluateAbstract (/Users/calebmer/prepack/lib/environment.js:1185:20)
    at LexicalEnvironment.evaluate (/Users/calebmer/prepack/lib/environment.js:1173:20)
    at LexicalEnvironment.evaluateCompletion (/Users/calebmer/prepack/lib/environment.js:942:19)
    at res.realm.statistics.evaluation.measure (/Users/calebmer/prepack/lib/environment.js:1029:65)
    at PerformanceTracker.measure (/Users/calebmer/prepack/lib/statistics.js:91:14)
    at LexicalEnvironment.executeSources (/Users/calebmer/prepack/lib/environment.js:1029:46)
    at Serializer._execute (/Users/calebmer/prepack/lib/serializer/serializer.js:90:40)
    at statistics.total.measure (/Users/calebmer/prepack/lib/serializer/serializer.js:154:23)
    at PerformanceTracker.measure (/Users/calebmer/prepack/lib/statistics.js:91:14)
    at Serializer.init (/Users/calebmer/prepack/lib/serializer/serializer.js:148:35)
    at prepackSources (/Users/calebmer/prepack/lib/prepack-standalone.js:71:33)
    at compileSource (/Users/calebmer/prepack/scripts/debug-fb-www.js:92:18)
    at compileFile (/Users/calebmer/prepack/scripts/debug-fb-www.js:129:31)
    at <anonymous>

Input

"use strict";

var object = {
  *["a"]() {
    yield 1;
    yield 2;
  },
};

x = Object.keys(object);

Output

"use strict";

var x, object;
(function () {
  var _$0 = this;

  var _3 = function () {
    yield 1; // <---------------------------------- Yield outside of generator!
    yield 2;
  };

  _$0.object = {
    a: _3
  };
  _$0.x = ["a"];
}).call(this);

This is not a great example, but it uncovers an issue I saw a lot of: “all native function values should be intrinsics.” Our visitor expects that all FunctionValues which make it to visitValueFunction are not NativeFunctionValues since these should be intrinsics.

https://github.com/facebook/prepack/blob/b0516b49ea50d8ce81af6d0518e8ec071866201a/src/serializer/ResidualHeapVisitor.js#L1025-L1035

However, NativeFunctionValues may have an undefined intrinsicName. Which makes them not an intrinsic!

https://github.com/facebook/prepack/blob/b0516b49ea50d8ce81af6d0518e8ec071866201a/src/values/NativeFunctionValue.js#L36-L45

You can see an example of this here:

https://github.com/facebook/prepack/blob/e170c37aaa996c75cb166671c5b6af442a227d5c/src/intrinsics/ecma262/ObjectPrototype.js#L130-L163

Input

var ThrowTypeError = Object.getOwnPropertyDescriptor(
  (function() {
    "use strict";
    return arguments;
  })(),
  "callee"
).get;

ThrowTypeError(); // Expected to throw `TypeError`

Error

Invariant Violation: all native function values should be intrinsics
This is likely a bug in Prepack, not your code. Feel free to open an issue on GitHub.
    at invariant (/Users/calebmer/prepack/lib/invariant.js:24:15)
    at ResidualHeapVisitor.visitValueFunction (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:509:28)
    at _enqueueWithUnrelatedScope (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:1026:45)
    at _withScope (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:1255:19)
    at ResidualHeapVisitor._withScope (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:208:7)
    at runGeneratorAction (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:1254:18)
    at ResidualHeapVisitor._visitUntilFixpoint (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:1310:11)
    at ResidualHeapVisitor.visitRoots (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:1196:10)
    at statistics.deepTraversal.measure (/Users/calebmer/prepack/lib/serializer/serializer.js:195:68)
    at PerformanceTracker.measure (/Users/calebmer/prepack/lib/statistics.js:91:14)
    at ast (/Users/calebmer/prepack/lib/serializer/serializer.js:195:34)
    at statistics.total.measure (/Users/calebmer/prepack/lib/serializer/serializer.js:230:9)
    at PerformanceTracker.measure (/Users/calebmer/prepack/lib/statistics.js:91:14)
    at Serializer.init (/Users/calebmer/prepack/lib/serializer/serializer.js:148:35)
    at prepackSources (/Users/calebmer/prepack/lib/prepack-standalone.js:71:33)
    at compileSource (/Users/calebmer/prepack/scripts/debug-fb-www.js:92:18)
    at compileFile (/Users/calebmer/prepack/scripts/debug-fb-www.js:129:31)
    at <anonymous>

Input

var obj = {
  method() {
    return super.toString;
  },
};

obj.toString = null;

inspect = function() {
  return obj.method() === Object.prototype.toString;
};

Output

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

  var _2 = function () {
    return super.toString; // <------------------------------ `super` is not allowed here!
  };

  var _3 = function () {
    return obj.method() === Object.prototype.toString;
  };

  _$0.obj = {
    method: _2,
    toString: null
  };
  _$0.inspect = _3;
}).call(this);

TypedArray is a global not exposed to the user JavaScript runtime. Try global.TypedArray in your JavaScript environment of choice. We must emit Object.getPrototypeOf(Int8Array) instead of TypedArray.

Input

var TypedArray = Object.getPrototypeOf(Int8Array);
console.log(TypedArray.from.name === "from");

Output

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

  var _$1 = _$0.TypedArray; // <-------------------- `TypedArray` is not exposed on the global object!
  _$0.TypedArray = _$1;
  console.log(true);
}.call(this));

Input

var TypedArray = Object.getPrototypeOf(Int8Array);
var TypedArrayPrototype = TypedArray.prototype;

Error

Invariant Violation:
This is likely a bug in Prepack, not your code. Feel free to open an issue on GitHub.
    at invariant (/Users/calebmer/prepack/lib/invariant.js:24:15)
    at ResidualHeapVisitor.visitValue (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:993:28)
    at ResidualHeapVisitor.visitEquivalentValue (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:987:10)
    at TemporalBuildNodeEntry.visit (/Users/calebmer/prepack/lib/utils/generator.js:105:82)
    at visitFn (/Users/calebmer/prepack/lib/utils/generator.js:855:46)
    at Generator.visit (/Users/calebmer/prepack/lib/utils/generator.js:863:7)
    at _withScope (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:1150:17)
    at ResidualHeapVisitor._withScope (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:208:7)
    at ResidualHeapVisitor.visitGenerator (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:1149:10)
    at ResidualHeapVisitor.visitRoots (/Users/calebmer/prepack/lib/serializer/ResidualHeapVisitor.js:1192:10)
    at statistics.deepTraversal.measure (/Users/calebmer/prepack/lib/serializer/serializer.js:195:68)
    at PerformanceTracker.measure (/Users/calebmer/prepack/lib/statistics.js:91:14)
    at ast (/Users/calebmer/prepack/lib/serializer/serializer.js:195:34)
    at statistics.total.measure (/Users/calebmer/prepack/lib/serializer/serializer.js:230:9)
    at PerformanceTracker.measure (/Users/calebmer/prepack/lib/statistics.js:91:14)
    at Serializer.init (/Users/calebmer/prepack/lib/serializer/serializer.js:148:35)
    at prepackSources (/Users/calebmer/prepack/lib/prepack-standalone.js:71:33)
    at compileSource (/Users/calebmer/prepack/scripts/debug-fb-www.js:92:18)
    at compileFile (/Users/calebmer/prepack/scripts/debug-fb-www.js:129:31)
    at <anonymous>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment