"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createFbMocks = createFbMocks;

var _index = require("../../domains/index.js");

var _index2 = require("../../values/index.js");

var _singletons = require("../../singletons.js");

var _index3 = require("../../methods/index.js");

var _babelTypes = require("babel-types");

var t = _interopRequireWildcard(_babelTypes);

var _invariant = require("../../invariant");

var _invariant2 = _interopRequireDefault(_invariant);

var _utils = require("../../react/utils.js");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

const fbMagicGlobalFunctions = ["asset", "cx", "cssVar", "csx", "errorDesc", "errorHelpCenterID", "errorSummary", "gkx", "glyph", "ifRequired", "ix", "fbglyph", "requireWeak", "xuiglyph"]; /**
                                                                                                                                                                                              * Copyright (c) 2017-present, Facebook, Inc.
                                                                                                                                                                                              * All rights reserved.
                                                                                                                                                                                              *
                                                                                                                                                                                              * This source code is licensed under the BSD-style license found in the
                                                                                                                                                                                              * LICENSE file in the root directory of this source tree. An additional grant
                                                                                                                                                                                              * of patent rights can be found in the PATENTS file in the same directory.
                                                                                                                                                                                              */

const fbMagicGlobalObjects = ["JSResource", "Bootloader"];

function createBabelHelpers(realm, global) {
  let babelHelpersValue = new _index2.ObjectValue(realm, realm.intrinsics.ObjectPrototype, `babelHelpers`, true);
  let objectAssign = (0, _index3.Get)(realm, realm.intrinsics.Object, "assign");
  let objectCreate = (0, _index3.Get)(realm, realm.intrinsics.Object, "create");

  //babelHelpers.objectWithoutProperties
  let inheritsValue = new _index2.NativeFunctionValue(realm, undefined, `inherits`, 2, (context, [subClass, superClass]) => {
    (0, _invariant2.default)(objectAssign instanceof _index2.NativeFunctionValue);
    let objectAssignCall = objectAssign.$Call;
    (0, _invariant2.default)(objectAssignCall !== undefined);
    objectAssignCall(realm.intrinsics.undefined, [subClass, superClass]);

    (0, _invariant2.default)(superClass instanceof _index2.ObjectValue);
    let superClassPrototype = (0, _index3.Get)(realm, superClass, "prototype");
    (0, _invariant2.default)(objectCreate instanceof _index2.NativeFunctionValue);
    let objectCreateCall = objectCreate.$Call;
    (0, _invariant2.default)(typeof objectCreateCall === "function");
    let newPrototype = objectCreateCall(realm.intrinsics.undefined, [superClassPrototype]);

    (0, _invariant2.default)(subClass instanceof _index2.ObjectValue);
    (0, _invariant2.default)(newPrototype instanceof _index2.ObjectValue);
    _singletons.Properties.Set(realm, subClass, "prototype", newPrototype, true);
    _singletons.Properties.Set(realm, newPrototype, "constructor", subClass, true);
    _singletons.Properties.Set(realm, subClass, "__superConstructor__", superClass, true);

    return superClass;
  });
  babelHelpersValue.$DefineOwnProperty("inherits", {
    value: inheritsValue,
    writable: false,
    enumerable: false,
    configurable: true
  });
  inheritsValue.intrinsicName = `babelHelpers.inherits`;

  //babelHelpers.objectWithoutProperties
  let objectWithoutPropertiesValue = new _index2.NativeFunctionValue(realm, undefined, `objectWithoutProperties`, 2, (context, [obj, keys]) => {
    (0, _invariant2.default)(obj instanceof _index2.ObjectValue || obj instanceof _index2.AbstractObjectValue || obj instanceof _index2.AbstractValue);
    (0, _invariant2.default)(keys instanceof _index2.ArrayValue);
    if (obj.isPartialObject() || obj instanceof _index2.AbstractObjectValue || obj instanceof _index2.AbstractValue) {
      let value = _index2.AbstractValue.createTemporalFromBuildFunction(realm, _index2.ObjectValue, [objectWithoutPropertiesValue, obj, keys], ([methodNode, objNode, propRemoveNode]) => {
        return t.callExpression(methodNode, [objNode, propRemoveNode]);
      });
      if (value instanceof _index2.AbstractObjectValue) {
        // as we are returning an abstract object, we mark it as simple
        value.makeSimple();
      }
      return value;
    } else {
      let removeKeys = new Set();
      (0, _utils.forEachArrayValue)(realm, keys, key => {
        if (key instanceof _index2.StringValue || key instanceof _index2.NumberValue) {
          removeKeys.add(key.value);
        }
      });
      let newObject = _singletons.Create.ObjectCreate(realm, realm.intrinsics.ObjectPrototype);
      for (let [propName, binding] of obj.properties) {
        if (!removeKeys.has(propName)) {
          if (binding && binding.descriptor && binding.descriptor.enumerable) {
            let value = (0, _index3.Get)(realm, obj, propName);
            _singletons.Properties.Set(realm, newObject, propName, value, true);
          }
        }
      }
      return newObject;
    }
  });
  babelHelpersValue.$DefineOwnProperty("objectWithoutProperties", {
    value: objectWithoutPropertiesValue,
    writable: false,
    enumerable: false,
    configurable: true
  });
  objectWithoutPropertiesValue.intrinsicName = `babelHelpers.objectWithoutProperties`;

  //babelHelpers.taggedTemplateLiteralLoose
  let taggedTemplateLiteralLooseValue = new _index2.NativeFunctionValue(realm, undefined, `taggedTemplateLiteralLoose`, 2, (context, [strings, raw]) => {
    (0, _invariant2.default)(strings instanceof _index2.ObjectValue);
    _singletons.Properties.Set(realm, strings, "raw", raw, true);
    return strings;
  });
  babelHelpersValue.$DefineOwnProperty("taggedTemplateLiteralLoose", {
    value: taggedTemplateLiteralLooseValue,
    writable: false,
    enumerable: false,
    configurable: true
  });
  taggedTemplateLiteralLooseValue.intrinsicName = `babelHelpers.taggedTemplateLiteralLoose`;

  //babelHelpers.extends & babelHelpers._extends
  babelHelpersValue.$DefineOwnProperty("extends", {
    value: objectAssign,
    writable: true,
    enumerable: true,
    configurable: true
  });

  babelHelpersValue.$DefineOwnProperty("_extends", {
    value: objectAssign,
    writable: true,
    enumerable: true,
    configurable: true
  });

  //babelHelpers.bind
  let functionBind = (0, _index3.Get)(realm, realm.intrinsics.FunctionPrototype, "bind");

  babelHelpersValue.$DefineOwnProperty("bind", {
    value: functionBind,
    writable: true,
    enumerable: true,
    configurable: true
  });

  global.$DefineOwnProperty("babelHelpers", {
    value: babelHelpersValue,
    writable: true,
    enumerable: true,
    configurable: true
  });
  babelHelpersValue.refuseSerialization = false;
}

function createMagicGlobalFunction(realm, global, functionName) {
  global.$DefineOwnProperty(functionName, {
    value: new _index2.NativeFunctionValue(realm, functionName, functionName, 0, (context, args) => {
      let types = new _index.TypesDomain(_index2.FunctionValue);
      let values = new _index.ValuesDomain();
      (0, _invariant2.default)(context.$Realm.generator);
      return context.$Realm.generator.derive(types, values, args, _args => t.callExpression(t.identifier(functionName), _args));
    }),
    writable: true,
    enumerable: false,
    configurable: true
  });
}

function createMagicGlobalObject(realm, global, objectName) {
  let globalObject = _index2.AbstractValue.createAbstractObject(realm, objectName);
  globalObject.kind = "resolved";

  global.$DefineOwnProperty(objectName, {
    value: globalObject,
    writable: true,
    enumerable: false,
    configurable: true
  });
}

function createFbMocks(realm, global) {
  global.$DefineOwnProperty("__DEV__", {
    // TODO: we'll likely want to make this configurable from the outside.
    value: realm.intrinsics.false,
    writable: true,
    enumerable: false,
    configurable: true
  });

  createBabelHelpers(realm, global);

  for (let functionName of fbMagicGlobalFunctions) {
    createMagicGlobalFunction(realm, global, functionName);
  }

  for (let objectName of fbMagicGlobalObjects) {
    createMagicGlobalObject(realm, global, objectName);
  }
}
//# sourceMappingURL=fb-mocks.js.map