<commit_before>var IS_PURE = require('../internals/is-pure');
var $ = require('../internals/export');
var global = require('../internals/global');
var getBuiltin = require('../internals/get-built-in');
var uncurryThis = require('../internals/function-uncurry-this');
var fails = require('../internals/fails');
var uid = require('../internals/uid');
var isCallable = require('../internals/is-callable');
var isConstructor = require('../internals/is-constructor');
var isObject = require('../internals/is-object');
var isSymbol = require('../internals/is-symbol');
var iterate = require('../internals/iterate');
var anObject = require('../internals/an-object');
var classof = require('../internals/classof');
var hasOwn = require('../internals/has-own-property');
var createProperty = require('../internals/create-property');
var createNonEnumerableProperty = require('../internals/create-non-enumerable-property');
var lengthOfArrayLike = require('../internals/length-of-array-like');
var regExpFlags = require('../internals/regexp-flags');
var ERROR_STACK_INSTALLABLE = require('../internals/error-stack-installable');

var Object = global.Object;
var Date = global.Date;
var Error = global.Error;
var EvalError = global.EvalError;
var RangeError = global.RangeError;
var ReferenceError = global.ReferenceError;
var SyntaxError = global.SyntaxError;
var TypeError = global.TypeError;
var URIError = global.URIError;
var PerformanceMark = global.PerformanceMark;
var WebAssembly = global.WebAssembly;
var CompileError = WebAssembly && WebAssembly.CompileError || Error;
var LinkError = WebAssembly && WebAssembly.LinkError || Error;
var RuntimeError = WebAssembly && WebAssembly.RuntimeError || Error;
var DOMException = getBuiltin('DOMException');
var Set = getBuiltin('Set');
var Map = getBuiltin('Map');
var MapPrototype = Map.prototype;
var mapHas = uncurryThis(MapPrototype.has);
var mapGet = uncurryThis(MapPrototype.get);
var mapSet = uncurryThis(MapPrototype.set);
var setAdd = uncurryThis(Set.prototype.add);
var objectKeys = getBuiltin('Object', 'keys');
var push = uncurryThis([].push);
var bolleanValueOf = uncurryThis(true.valueOf);
var numberValueOf = uncurryThis(1.0.valueOf);
var stringValueOf = uncurryThis(''.valueOf);
var getFlags = uncurryThis(regExpFlags);
var getTime = uncurryThis(Date.prototype.getTime);
var PERFORMANCE_MARK = uid('structuredClone');
var DATA_CLONE_ERROR = 'DataCloneError';
var TRANSFERRING = 'Transferring';

var checkBasicSemantic = function (structuredCloneImplementation) {
  return !fails(function () {
    var set1 = new global.Set([7]);
    var set2 = structuredCloneImplementation(set1);
    var number = structuredCloneImplementation(Object(7));
    return set2 == set1 || !set2.has(7) || typeof number != 'object' || number != 7;
  }) && structuredCloneImplementation;
};

// https://github.com/whatwg/html/pull/5749
var checkNewErrorsSemantic = function (structuredCloneImplementation) {
  return !fails(function () {
    var test = structuredCloneImplementation(new global.AggregateError([1], PERFORMANCE_MARK, { cause: 3 }));
    return test.name != 'AggregateError' || test.errors[0] != 1 || test.message != PERFORMANCE_MARK || test.cause != 3;
  }) && structuredCloneImplementation;
};

// FF94+, Safari TP134+, Chrome Canary 98+, NodeJS 17.0+, Deno 1.13+
// current FF and Safari implementations can't clone errors
// https://bugzilla.mozilla.org/show_bug.cgi?id=1556604
// no one of current implementations supports new (html/5749) error cloning semantic
var nativeStructuredClone = global.structuredClone;

var FORCED_REPLACEMENT = IS_PURE || !checkNewErrorsSemantic(nativeStructuredClone);

// Chrome 82+, Safari 14.1+, Deno 1.11+
// Chrome 78-81 implementation swaps `.name` and `.message` of cloned `DOMException`
// Safari 14.1 implementation doesn't clone some `RegExp` flags, so requires a workaround
// current Safari implementation can't clone errors
// Deno 1.2-1.10 implementations too naive
// NodeJS 16.0+ does not have `PerformanceMark` constructor, structured cloning implementation
//   from `performance.mark` is too naive and can't clone, for example, `RegExp` or some boxed primitives
//   https://github.com/nodejs/node/issues/40840
// no one of current implementations supports new (html/5749) error cloning semantic
var structuredCloneFromMark = !nativeStructuredClone && checkBasicSemantic(function (value) {
  return new PerformanceMark(PERFORMANCE_MARK, { detail: value }).detail;
});

var nativeRestrictedStructuredClone = checkBasicSemantic(nativeStructuredClone) || structuredCloneFromMark;

var throwUncloneable = function (type) {
  throw new DOMException('Uncloneable type: ' + type, DATA_CLONE_ERROR);
};

var throwUnpolyfillable = function (type, kind) {
  throw new DOMException((kind || 'Cloning') + ' of ' + type + ' cannot be properly polyfilled in this engine', DATA_CLONE_ERROR);
};

var structuredCloneInternal = function (value, map) {
  if (isSymbol(value)) throwUncloneable('Symbol');
  if (!isObject(value)) return value;
  // effectively preserves circular references
  if (map) {
    if (mapHas(map, value)) return mapGet(map, value);
  } else map = new Map();

  var type = classof(value);
  var deep = false;
  var C, name, cloned, dataTransfer, i, length, keys, key;

  switch (type) {
    case 'Array':
      cloned = [];
      deep = true;
      break;
    case 'Object':
      cloned = {};
      deep = true;
      break;
    case 'Map':
      cloned = new Map();
      deep = true;
      break;
    case 'Set':
      cloned = new Set();
      deep = true;
      break;
    case 'RegExp':
      // in this block because of a Safari 14.1 bug
      // old FF does not clone regexes passed to the constructor, so get the source and flags directly
      cloned = new RegExp(value.source, 'flags' in value ? value.flags : getFlags(value));
      break;
    case 'Error':
      name = value.name;
      switch (name) {
        case 'AggregateError':
          cloned = getBuiltin('AggregateError')([]);
          break;
        case 'EvalError':
          cloned = EvalError();
          break;
        case 'RangeError':
          cloned = RangeError();
          break;
        case 'ReferenceError':
          cloned = ReferenceError();
          break;
        case 'SyntaxError':
          cloned = SyntaxError();
          break;
        case 'TypeError':
          cloned = TypeError();
          break;
        case 'URIError':
          cloned = URIError();
          break;
        case 'CompileError':
          cloned = CompileError();
          break;
        case 'LinkError':
          cloned = LinkError();
          break;
        case 'RuntimeError':
          cloned = RuntimeError();
          break;
        default:
          cloned = Error();
      }
      deep = true;
      break;
    case 'DOMException':
      cloned = new DOMException(value.message, value.name);
      deep = true;
      break;
    case 'DataView':
    case 'Int8Array':
    case 'Uint8Array':
    case 'Uint8ClampedArray':
    case 'Int16Array':
    case 'Uint16Array':
    case 'Int32Array':
    case 'Uint32Array':
    case 'Float32Array':
    case 'Float64Array':
    case 'BigInt64Array':
    case 'BigUint64Array':
      C = global[type];
      if (!isConstructor(C)) throwUnpolyfillable(type);
      cloned = new C(
        // this is safe, since arraybuffer cannot have circular references
        structuredCloneInternal(value.buffer, map),
        value.byteOffset,
        type === 'DataView' ? value.byteLength : value.length
      );
      break;
    case 'DOMQuad':
      C = global.DOMQuad;
      if (isConstructor(C)) {
        cloned = new C(
          structuredCloneInternal(value.p1, map),
          structuredCloneInternal(value.p2, map),
          structuredCloneInternal(value.p3, map),
          structuredCloneInternal(value.p4, map)
        );
      } else if (nativeRestrictedStructuredClone) {
        cloned = nativeRestrictedStructuredClone(value);
      } else throwUnpolyfillable(type);
      break;
    case 'FileList':
      C = global.DataTransfer;
      if (isConstructor(C)) {
        dataTransfer = new C();
        for (i = 0, length = lengthOfArrayLike(value); i < length; i++) {
          dataTransfer.items.add(structuredCloneInternal(value[i], map));
        }
        cloned = dataTransfer.files;
      } else if (nativeRestrictedStructuredClone) {
        cloned = nativeRestrictedStructuredClone(value);
      } else throwUnpolyfillable(type);
      break;
    case 'ImageData':
      // Safari 9 ImageData is a constructor, but typeof ImageData is 'object'
      try {
        cloned = new ImageData(
          structuredCloneInternal(value.data, map),
          value.width,
          value.height,
          { colorSpace: value.colorSpace }
        );
      } catch (error) {
        if (nativeRestrictedStructuredClone) {
          cloned = nativeRestrictedStructuredClone(value);
        } else throwUnpolyfillable(type);
      } break;
    default:
      if (nativeRestrictedStructuredClone) {
        cloned = nativeRestrictedStructuredClone(value);
      } else switch (type) {
        case 'BigInt':
          // can be a 3rd party polyfill
          cloned = Object(value.valueOf());
          break;
        case 'Boolean':
          cloned = Object(bolleanValueOf(value));
          break;
        case 'Number':
          cloned = Object(numberValueOf(value));
          break;
        case 'String':
          cloned = Object(stringValueOf(value));
          break;
        case 'Date':
          cloned = new Date(getTime(value));
          break;
        case 'ArrayBuffer':
          // detached buffers throws on `.slice`
          try {
            cloned = value.slice(0);
          } catch (error) {
            throw new DOMException('ArrayBuffer is deatched', DATA_CLONE_ERROR);
          } break;
        case 'SharedArrayBuffer':
          // SharedArrayBuffer should use shared memory, we can't polyfill it, so return the original
          cloned = value;
          break;
        case 'Blob':
          try {
            cloned = value.slice(0, value.size, value.type);
          } catch (error) {
            throwUnpolyfillable(type);
          } break;
        case 'DOMPoint':
        case 'DOMPointReadOnly':
          C = global[type];
          try {
            cloned = C.fromPoint
              ? C.fromPoint(value)
              : new C(value.x, value.y, value.z, value.w);
          } catch (error) {
            throwUnpolyfillable(type);
          } break;
        case 'DOMRect':
        case 'DOMRectReadOnly':
          C = global[type];
          try {
            cloned = C.fromRect
              ? C.fromRect(value)
              : new C(value.x, value.y, value.width, value.height);
          } catch (error) {
            throwUnpolyfillable(type);
          } break;
        case 'DOMMatrix':
        case 'DOMMatrixReadOnly':
          C = global[type];
          try {
            cloned = C.fromMatrix
              ? C.fromMatrix(value)
              : new C(value);
          } catch (error) {
            throwUnpolyfillable(type);
          } break;
        case 'AudioData':
        case 'VideoFrame':
          if (!isCallable(value.clone)) throwUnpolyfillable(type);
          try {
            cloned = value.clone();
          } catch (error) {
            throwUncloneable(type);
          } break;
        case 'File':
          try {
            cloned = new File([value], value.name, value);
          } catch (error) {
            throwUnpolyfillable(type);
          } break;
        case 'CryptoKey':
        case 'GPUCompilationMessage':
        case 'GPUCompilationInfo':
        case 'ImageBitmap':
        case 'RTCCertificate':
        case 'WebAssembly.Module':
          throwUnpolyfillable(type);
          // break omitted
        default:
          throwUncloneable(type);
      }
  }

  mapSet(map, value, cloned);

  if (deep) switch (type) {
    case 'Array':
    case 'Object':
      keys = objectKeys(value);
      for (i = 0, length = lengthOfArrayLike(keys); i < length; i++) {
        key = keys[i];
        createProperty(cloned, key, structuredCloneInternal(value[key], map));
      } break;
    case 'Map':
      value.forEach(function (v, k) {
        mapSet(cloned, structuredCloneInternal(k, map), structuredCloneInternal(v, map));
      });
      break;
    case 'Set':
      value.forEach(function (v) {
        setAdd(cloned, structuredCloneInternal(v, map));
      });
      break;
    case 'Error':
      createNonEnumerableProperty(cloned, 'message', structuredCloneInternal(value.message, map));
      if (hasOwn(value, 'cause')) {
        createNonEnumerableProperty(cloned, 'cause', structuredCloneInternal(value.cause, map));
      }
      if (name == 'AggregateError') {
        cloned.errors = structuredCloneInternal(value.errors, map);
      } // break omitted
    case 'DOMException':
      if (ERROR_STACK_INSTALLABLE) {
        createNonEnumerableProperty(cloned, 'stack', structuredCloneInternal(value.stack, map));
      }
  }

  return cloned;
};

var PROPER_TRANSFER = nativeStructuredClone && !fails(function () {
  var buffer = new global.ArrayBuffer(8);
  var clone = nativeStructuredClone(buffer, { transfer: [buffer] });
  return buffer.byteLength != 0 || clone.byteLength != 8;
});

var tryToTransfer = function (rawTransfer, map) {
  if (!isObject(rawTransfer)) throw TypeError('Transfer option cannot be converted to a sequence');

  var transfer = [];

  iterate(rawTransfer, function (value) {
    push(transfer, anObject(value));
  });

  var i = 0;
  var length = lengthOfArrayLike(transfer);
  var value, type, C, transferredArray, transferred, canvas, context;

  if (PROPER_TRANSFER) {
    transferredArray = nativeStructuredClone(transfer, { transfer: transfer });
    while (i < length) mapSet(map, transfer[i], transferredArray[i++]);
  } else while (i < length) {
    value = transfer[i++];
    if (mapHas(map, value)) throw new DOMException('Duplicate transferable', DATA_CLONE_ERROR);

    type = classof(value);

    switch (type) {
      case 'ImageBitmap':
        C = global.OffscreenCanvas;
        if (!isConstructor(C)) throwUnpolyfillable(type, TRANSFERRING);
        try {
          canvas = new C(value.width, value.height);
          context = canvas.getContext('bitmaprenderer');
          context.transferFromImageBitmap(value);
          transferred = canvas.transferToImageBitmap();
        } catch (error) { /* empty */ }
        break;
      case 'AudioData':
      case 'VideoFrame':
        if (!isCallable(value.clone) || !isCallable(value.close)) throwUnpolyfillable(type, TRANSFERRING);
        try {
          transferred = value.clone();
          value.close();
        } catch (error) { /* empty */ }
        break;
      case 'ArrayBuffer':
      case 'MessagePort':
      case 'OffscreenCanvas':
      case 'ReadableStream':
      case 'TransformStream':
      case 'WritableStream':
        throwUnpolyfillable(type, TRANSFERRING);
    }

    if (transferred === undefined) throw new DOMException('This object cannot be transferred: ' + type, DATA_CLONE_ERROR);
    mapSet(map, value, transferred);
  }
};

$({ global: true, enumerable: true, sham: !PROPER_TRANSFER, forced: FORCED_REPLACEMENT }, {
  structuredClone: function structuredClone(value /* , { transfer } */) {
    var options = arguments.length > 1 ? anObject(arguments[1]) : undefined;
    var transfer = options ? options.transfer : undefined;
    var map;

    if (transfer !== undefined) {
      map = new Map();
      tryToTransfer(transfer, map);
    }

    return structuredCloneInternal(value, map);
  }
});
<commit_msg>workaround missed `ArrayBuffer#slice` in IE10 in the pure mode<commit_after>var IS_PURE = require('../internals/is-pure');
var $ = require('../internals/export');
var global = require('../internals/global');
var getBuiltin = require('../internals/get-built-in');
var uncurryThis = require('../internals/function-uncurry-this');
var fails = require('../internals/fails');
var uid = require('../internals/uid');
var isCallable = require('../internals/is-callable');
var isConstructor = require('../internals/is-constructor');
var isObject = require('../internals/is-object');
var isSymbol = require('../internals/is-symbol');
var iterate = require('../internals/iterate');
var anObject = require('../internals/an-object');
var classof = require('../internals/classof');
var hasOwn = require('../internals/has-own-property');
var createProperty = require('../internals/create-property');
var createNonEnumerableProperty = require('../internals/create-non-enumerable-property');
var lengthOfArrayLike = require('../internals/length-of-array-like');
var regExpFlags = require('../internals/regexp-flags');
var ERROR_STACK_INSTALLABLE = require('../internals/error-stack-installable');

var Object = global.Object;
var Date = global.Date;
var Error = global.Error;
var EvalError = global.EvalError;
var RangeError = global.RangeError;
var ReferenceError = global.ReferenceError;
var SyntaxError = global.SyntaxError;
var TypeError = global.TypeError;
var URIError = global.URIError;
var PerformanceMark = global.PerformanceMark;
var WebAssembly = global.WebAssembly;
var CompileError = WebAssembly && WebAssembly.CompileError || Error;
var LinkError = WebAssembly && WebAssembly.LinkError || Error;
var RuntimeError = WebAssembly && WebAssembly.RuntimeError || Error;
var DOMException = getBuiltin('DOMException');
var Set = getBuiltin('Set');
var Map = getBuiltin('Map');
var MapPrototype = Map.prototype;
var mapHas = uncurryThis(MapPrototype.has);
var mapGet = uncurryThis(MapPrototype.get);
var mapSet = uncurryThis(MapPrototype.set);
var setAdd = uncurryThis(Set.prototype.add);
var objectKeys = getBuiltin('Object', 'keys');
var push = uncurryThis([].push);
var bolleanValueOf = uncurryThis(true.valueOf);
var numberValueOf = uncurryThis(1.0.valueOf);
var stringValueOf = uncurryThis(''.valueOf);
var getFlags = uncurryThis(regExpFlags);
var getTime = uncurryThis(Date.prototype.getTime);
var PERFORMANCE_MARK = uid('structuredClone');
var DATA_CLONE_ERROR = 'DataCloneError';
var TRANSFERRING = 'Transferring';

var checkBasicSemantic = function (structuredCloneImplementation) {
  return !fails(function () {
    var set1 = new global.Set([7]);
    var set2 = structuredCloneImplementation(set1);
    var number = structuredCloneImplementation(Object(7));
    return set2 == set1 || !set2.has(7) || typeof number != 'object' || number != 7;
  }) && structuredCloneImplementation;
};

// https://github.com/whatwg/html/pull/5749
var checkNewErrorsSemantic = function (structuredCloneImplementation) {
  return !fails(function () {
    var test = structuredCloneImplementation(new global.AggregateError([1], PERFORMANCE_MARK, { cause: 3 }));
    return test.name != 'AggregateError' || test.errors[0] != 1 || test.message != PERFORMANCE_MARK || test.cause != 3;
  }) && structuredCloneImplementation;
};

// FF94+, Safari TP134+, Chrome Canary 98+, NodeJS 17.0+, Deno 1.13+
// current FF and Safari implementations can't clone errors
// https://bugzilla.mozilla.org/show_bug.cgi?id=1556604
// no one of current implementations supports new (html/5749) error cloning semantic
var nativeStructuredClone = global.structuredClone;

var FORCED_REPLACEMENT = IS_PURE || !checkNewErrorsSemantic(nativeStructuredClone);

// Chrome 82+, Safari 14.1+, Deno 1.11+
// Chrome 78-81 implementation swaps `.name` and `.message` of cloned `DOMException`
// Safari 14.1 implementation doesn't clone some `RegExp` flags, so requires a workaround
// current Safari implementation can't clone errors
// Deno 1.2-1.10 implementations too naive
// NodeJS 16.0+ does not have `PerformanceMark` constructor, structured cloning implementation
//   from `performance.mark` is too naive and can't clone, for example, `RegExp` or some boxed primitives
//   https://github.com/nodejs/node/issues/40840
// no one of current implementations supports new (html/5749) error cloning semantic
var structuredCloneFromMark = !nativeStructuredClone && checkBasicSemantic(function (value) {
  return new PerformanceMark(PERFORMANCE_MARK, { detail: value }).detail;
});

var nativeRestrictedStructuredClone = checkBasicSemantic(nativeStructuredClone) || structuredCloneFromMark;

var throwUncloneable = function (type) {
  throw new DOMException('Uncloneable type: ' + type, DATA_CLONE_ERROR);
};

var throwUnpolyfillable = function (type, kind) {
  throw new DOMException((kind || 'Cloning') + ' of ' + type + ' cannot be properly polyfilled in this engine', DATA_CLONE_ERROR);
};

var structuredCloneInternal = function (value, map) {
  if (isSymbol(value)) throwUncloneable('Symbol');
  if (!isObject(value)) return value;
  // effectively preserves circular references
  if (map) {
    if (mapHas(map, value)) return mapGet(map, value);
  } else map = new Map();

  var type = classof(value);
  var deep = false;
  var C, name, cloned, dataTransfer, i, length, keys, key, source, target;

  switch (type) {
    case 'Array':
      cloned = [];
      deep = true;
      break;
    case 'Object':
      cloned = {};
      deep = true;
      break;
    case 'Map':
      cloned = new Map();
      deep = true;
      break;
    case 'Set':
      cloned = new Set();
      deep = true;
      break;
    case 'RegExp':
      // in this block because of a Safari 14.1 bug
      // old FF does not clone regexes passed to the constructor, so get the source and flags directly
      cloned = new RegExp(value.source, 'flags' in value ? value.flags : getFlags(value));
      break;
    case 'Error':
      name = value.name;
      switch (name) {
        case 'AggregateError':
          cloned = getBuiltin('AggregateError')([]);
          break;
        case 'EvalError':
          cloned = EvalError();
          break;
        case 'RangeError':
          cloned = RangeError();
          break;
        case 'ReferenceError':
          cloned = ReferenceError();
          break;
        case 'SyntaxError':
          cloned = SyntaxError();
          break;
        case 'TypeError':
          cloned = TypeError();
          break;
        case 'URIError':
          cloned = URIError();
          break;
        case 'CompileError':
          cloned = CompileError();
          break;
        case 'LinkError':
          cloned = LinkError();
          break;
        case 'RuntimeError':
          cloned = RuntimeError();
          break;
        default:
          cloned = Error();
      }
      deep = true;
      break;
    case 'DOMException':
      cloned = new DOMException(value.message, value.name);
      deep = true;
      break;
    case 'DataView':
    case 'Int8Array':
    case 'Uint8Array':
    case 'Uint8ClampedArray':
    case 'Int16Array':
    case 'Uint16Array':
    case 'Int32Array':
    case 'Uint32Array':
    case 'Float32Array':
    case 'Float64Array':
    case 'BigInt64Array':
    case 'BigUint64Array':
      C = global[type];
      if (!isConstructor(C)) throwUnpolyfillable(type);
      cloned = new C(
        // this is safe, since arraybuffer cannot have circular references
        structuredCloneInternal(value.buffer, map),
        value.byteOffset,
        type === 'DataView' ? value.byteLength : value.length
      );
      break;
    case 'DOMQuad':
      C = global.DOMQuad;
      if (isConstructor(C)) {
        cloned = new C(
          structuredCloneInternal(value.p1, map),
          structuredCloneInternal(value.p2, map),
          structuredCloneInternal(value.p3, map),
          structuredCloneInternal(value.p4, map)
        );
      } else if (nativeRestrictedStructuredClone) {
        cloned = nativeRestrictedStructuredClone(value);
      } else throwUnpolyfillable(type);
      break;
    case 'FileList':
      C = global.DataTransfer;
      if (isConstructor(C)) {
        dataTransfer = new C();
        for (i = 0, length = lengthOfArrayLike(value); i < length; i++) {
          dataTransfer.items.add(structuredCloneInternal(value[i], map));
        }
        cloned = dataTransfer.files;
      } else if (nativeRestrictedStructuredClone) {
        cloned = nativeRestrictedStructuredClone(value);
      } else throwUnpolyfillable(type);
      break;
    case 'ImageData':
      // Safari 9 ImageData is a constructor, but typeof ImageData is 'object'
      try {
        cloned = new ImageData(
          structuredCloneInternal(value.data, map),
          value.width,
          value.height,
          { colorSpace: value.colorSpace }
        );
      } catch (error) {
        if (nativeRestrictedStructuredClone) {
          cloned = nativeRestrictedStructuredClone(value);
        } else throwUnpolyfillable(type);
      } break;
    default:
      if (nativeRestrictedStructuredClone) {
        cloned = nativeRestrictedStructuredClone(value);
      } else switch (type) {
        case 'BigInt':
          // can be a 3rd party polyfill
          cloned = Object(value.valueOf());
          break;
        case 'Boolean':
          cloned = Object(bolleanValueOf(value));
          break;
        case 'Number':
          cloned = Object(numberValueOf(value));
          break;
        case 'String':
          cloned = Object(stringValueOf(value));
          break;
        case 'Date':
          cloned = new Date(getTime(value));
          break;
        case 'ArrayBuffer':
          // detached buffers throws in `DataView` and `.slice`
          try {
            // `ArrayBuffer#slice` is not available in IE10
            if (typeof value.slice == 'function') {
              cloned = value.slice(0);
            } else {
              length = value.byteLength;
              cloned = new ArrayBuffer(length);
              // eslint-disable-next-line es/no-typed-arrays -- ok
              source = new DataView(value);
              // eslint-disable-next-line es/no-typed-arrays -- ok
              target = new DataView(cloned);
              for (i = 0; i < length; i++) {
                target.setUint8(i, source.getUint8(i));
              }
            }
          } catch (error) {
            throw new DOMException('ArrayBuffer is deatched', DATA_CLONE_ERROR);
          } break;
        case 'SharedArrayBuffer':
          // SharedArrayBuffer should use shared memory, we can't polyfill it, so return the original
          cloned = value;
          break;
        case 'Blob':
          try {
            cloned = value.slice(0, value.size, value.type);
          } catch (error) {
            throwUnpolyfillable(type);
          } break;
        case 'DOMPoint':
        case 'DOMPointReadOnly':
          C = global[type];
          try {
            cloned = C.fromPoint
              ? C.fromPoint(value)
              : new C(value.x, value.y, value.z, value.w);
          } catch (error) {
            throwUnpolyfillable(type);
          } break;
        case 'DOMRect':
        case 'DOMRectReadOnly':
          C = global[type];
          try {
            cloned = C.fromRect
              ? C.fromRect(value)
              : new C(value.x, value.y, value.width, value.height);
          } catch (error) {
            throwUnpolyfillable(type);
          } break;
        case 'DOMMatrix':
        case 'DOMMatrixReadOnly':
          C = global[type];
          try {
            cloned = C.fromMatrix
              ? C.fromMatrix(value)
              : new C(value);
          } catch (error) {
            throwUnpolyfillable(type);
          } break;
        case 'AudioData':
        case 'VideoFrame':
          if (!isCallable(value.clone)) throwUnpolyfillable(type);
          try {
            cloned = value.clone();
          } catch (error) {
            throwUncloneable(type);
          } break;
        case 'File':
          try {
            cloned = new File([value], value.name, value);
          } catch (error) {
            throwUnpolyfillable(type);
          } break;
        case 'CryptoKey':
        case 'GPUCompilationMessage':
        case 'GPUCompilationInfo':
        case 'ImageBitmap':
        case 'RTCCertificate':
        case 'WebAssembly.Module':
          throwUnpolyfillable(type);
          // break omitted
        default:
          throwUncloneable(type);
      }
  }

  mapSet(map, value, cloned);

  if (deep) switch (type) {
    case 'Array':
    case 'Object':
      keys = objectKeys(value);
      for (i = 0, length = lengthOfArrayLike(keys); i < length; i++) {
        key = keys[i];
        createProperty(cloned, key, structuredCloneInternal(value[key], map));
      } break;
    case 'Map':
      value.forEach(function (v, k) {
        mapSet(cloned, structuredCloneInternal(k, map), structuredCloneInternal(v, map));
      });
      break;
    case 'Set':
      value.forEach(function (v) {
        setAdd(cloned, structuredCloneInternal(v, map));
      });
      break;
    case 'Error':
      createNonEnumerableProperty(cloned, 'message', structuredCloneInternal(value.message, map));
      if (hasOwn(value, 'cause')) {
        createNonEnumerableProperty(cloned, 'cause', structuredCloneInternal(value.cause, map));
      }
      if (name == 'AggregateError') {
        cloned.errors = structuredCloneInternal(value.errors, map);
      } // break omitted
    case 'DOMException':
      if (ERROR_STACK_INSTALLABLE) {
        createNonEnumerableProperty(cloned, 'stack', structuredCloneInternal(value.stack, map));
      }
  }

  return cloned;
};

var PROPER_TRANSFER = nativeStructuredClone && !fails(function () {
  var buffer = new ArrayBuffer(8);
  var clone = nativeStructuredClone(buffer, { transfer: [buffer] });
  return buffer.byteLength != 0 || clone.byteLength != 8;
});

var tryToTransfer = function (rawTransfer, map) {
  if (!isObject(rawTransfer)) throw TypeError('Transfer option cannot be converted to a sequence');

  var transfer = [];

  iterate(rawTransfer, function (value) {
    push(transfer, anObject(value));
  });

  var i = 0;
  var length = lengthOfArrayLike(transfer);
  var value, type, C, transferredArray, transferred, canvas, context;

  if (PROPER_TRANSFER) {
    transferredArray = nativeStructuredClone(transfer, { transfer: transfer });
    while (i < length) mapSet(map, transfer[i], transferredArray[i++]);
  } else while (i < length) {
    value = transfer[i++];
    if (mapHas(map, value)) throw new DOMException('Duplicate transferable', DATA_CLONE_ERROR);

    type = classof(value);

    switch (type) {
      case 'ImageBitmap':
        C = global.OffscreenCanvas;
        if (!isConstructor(C)) throwUnpolyfillable(type, TRANSFERRING);
        try {
          canvas = new C(value.width, value.height);
          context = canvas.getContext('bitmaprenderer');
          context.transferFromImageBitmap(value);
          transferred = canvas.transferToImageBitmap();
        } catch (error) { /* empty */ }
        break;
      case 'AudioData':
      case 'VideoFrame':
        if (!isCallable(value.clone) || !isCallable(value.close)) throwUnpolyfillable(type, TRANSFERRING);
        try {
          transferred = value.clone();
          value.close();
        } catch (error) { /* empty */ }
        break;
      case 'ArrayBuffer':
      case 'MessagePort':
      case 'OffscreenCanvas':
      case 'ReadableStream':
      case 'TransformStream':
      case 'WritableStream':
        throwUnpolyfillable(type, TRANSFERRING);
    }

    if (transferred === undefined) throw new DOMException('This object cannot be transferred: ' + type, DATA_CLONE_ERROR);
    mapSet(map, value, transferred);
  }
};

$({ global: true, enumerable: true, sham: !PROPER_TRANSFER, forced: FORCED_REPLACEMENT }, {
  structuredClone: function structuredClone(value /* , { transfer } */) {
    var options = arguments.length > 1 ? anObject(arguments[1]) : undefined;
    var transfer = options ? options.transfer : undefined;
    var map;

    if (transfer !== undefined) {
      map = new Map();
      tryToTransfer(transfer, map);
    }

    return structuredCloneInternal(value, map);
  }
});
<|endoftext|>


<commit_before>'use strict';

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

var _regenerator = require('babel-runtime/regenerator');

var _regenerator2 = _interopRequireDefault(_regenerator);

var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');

var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);

exports.default = function (client, name, keyPair) {
  var _this = this;

  var defaultValue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};

  var record = client.record.getRecord(name);
  var readyPromise = new Promise(function (resolve, reject) {
    record.once('ready', resolve);
    record.once('error', reject);
  });
  var pemPublicKey = keyPair.exportKey('pkcs1-public-pem');
  var currentData = {};
  readyPromise.then(function () {
    currentData = record.get();
  });
  var callbacks = {};
  var errbacks = new Set([]);
  var getSignature = function getSignature(value) {
    var data = Object.assign({}, value);
    delete data.signature;
    var pairs = Object.keys(data).map(function (key) {
      return [key, data[key]];
    });
    pairs.sort(function (x, y) {
      return x[0] > y[0] ? 1 : -1;
    });
    var pairString = JSON.stringify(pairs);
    var signature = keyPair.sign(pairString).toString('base64');
    return signature;
  };
  record.subscribe(function () {
    var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(value) {
      var data, signature, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, errback;

      return _regenerator2.default.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.prev = 0;
              data = Object.assign({}, value);
              signature = data.signature;

              delete data.signature;

              if (!(Object.keys(data).length > 0 && signature !== getSignature(data))) {
                _context.next = 6;
                break;
              }

              throw new Error('Invalid signature for record ' + name);

            case 6:
              Object.keys(currentData).forEach(function (k) {
                if (!data[k] && callbacks[k]) {
                  callbacks[k].forEach(function (callback) {
                    return callback();
                  });
                }
              });
              Object.keys(data).forEach(function (k) {
                if (data[k] !== currentData[k] && callbacks[k]) {
                  callbacks[k].forEach(function (callback) {
                    return callback(data[k]);
                  });
                }
              });
              currentData = data;
              _context.next = 32;
              break;

            case 11:
              _context.prev = 11;
              _context.t0 = _context['catch'](0);
              _iteratorNormalCompletion = true;
              _didIteratorError = false;
              _iteratorError = undefined;
              _context.prev = 16;

              for (_iterator = errbacks[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                errback = _step.value;
                // eslint-disable-line no-restricted-syntax
                errback(_context.t0);
              }
              _context.next = 24;
              break;

            case 20:
              _context.prev = 20;
              _context.t1 = _context['catch'](16);
              _didIteratorError = true;
              _iteratorError = _context.t1;

            case 24:
              _context.prev = 24;
              _context.prev = 25;

              if (!_iteratorNormalCompletion && _iterator.return) {
                _iterator.return();
              }

            case 27:
              _context.prev = 27;

              if (!_didIteratorError) {
                _context.next = 30;
                break;
              }

              throw _iteratorError;

            case 30:
              return _context.finish(27);

            case 31:
              return _context.finish(24);

            case 32:
            case 'end':
              return _context.stop();
          }
        }
      }, _callee, _this, [[0, 11], [16, 20, 24, 32], [25,, 27, 31]]);
    }));

    return function (_x2) {
      return _ref.apply(this, arguments);
    };
  }(), true);
  var subscribe = function subscribe(key, callback, errback) {
    callbacks[key] = callbacks[key] || [];
    callbacks[key].push(callback);
    readyPromise.then(function () {
      return callback(currentData[key]);
    });
    if (errback) {
      errbacks.add(errback);
    }
  };
  var discard = function () {
    var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
      return _regenerator2.default.wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              if (!record.isDestroyed) {
                _context2.next = 2;
                break;
              }

              return _context2.abrupt('return');

            case 2:
              record.unsubscribe();
              _context2.next = 5;
              return new Promise(function (resolve, reject) {
                record.once('discard', resolve);
                record.once('error', reject);
                record.discard();
              });

            case 5:
            case 'end':
              return _context2.stop();
          }
        }
      }, _callee2, _this);
    }));

    return function discard() {
      return _ref2.apply(this, arguments);
    };
  }();
  var set = function () {
    var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(key, value) {
      var remoteValue, data;
      return _regenerator2.default.wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              _context3.next = 2;
              return readyPromise;

            case 2:
              remoteValue = record.get();

              if (Object.keys(remoteValue).length > 0 && remoteValue.signature !== getSignature(remoteValue)) {
                console.error('Invalid signature for record ' + name + ', clearing.'); // eslint-disable-line no-console
                remoteValue = {};
              }
              data = Object.assign({}, remoteValue, defaultValue, {
                publicKey: pemPublicKey
              });

              data[key] = value;
              data.signature = getSignature(data);
              _context3.next = 9;
              return new Promise(function (resolve, reject) {
                record.set(data, function (errorMessage) {
                  if (errorMessage) {
                    reject(new Error(errorMessage));
                  } else {
                    resolve();
                  }
                });
              });

            case 9:
            case 'end':
              return _context3.stop();
          }
        }
      }, _callee3, _this);
    }));

    return function set(_x3, _x4) {
      return _ref3.apply(this, arguments);
    };
  }();
  return { set: set, subscribe: subscribe, discard: discard };
};

var _deepstream = require('deepstream.io-client-js');

var _deepstream2 = _interopRequireDefault(_deepstream);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }<commit_msg>Remove ready callback<commit_after>'use strict';

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

var _regenerator = require('babel-runtime/regenerator');

var _regenerator2 = _interopRequireDefault(_regenerator);

var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');

var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);

exports.default = function (client, name, keyPair) {
  var _this = this;

  var defaultValue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};

  var record = client.record.getRecord(name);
  var readyPromise = new Promise(function (resolve, reject) {
    record.once('ready', resolve);
    record.once('error', reject);
  });
  var pemPublicKey = keyPair.exportKey('pkcs1-public-pem');
  var currentData = {};
  readyPromise.then(function () {
    currentData = record.get();
  });
  var callbacks = {};
  var errbacks = new Set([]);
  var getSignature = function getSignature(value) {
    var data = Object.assign({}, value);
    delete data.signature;
    var pairs = Object.keys(data).map(function (key) {
      return [key, data[key]];
    });
    pairs.sort(function (x, y) {
      return x[0] > y[0] ? 1 : -1;
    });
    var pairString = JSON.stringify(pairs);
    var signature = keyPair.sign(pairString).toString('base64');
    return signature;
  };
  record.subscribe(function () {
    var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(value) {
      var data, signature, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, errback;

      return _regenerator2.default.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.prev = 0;
              data = Object.assign({}, value);
              signature = data.signature;

              delete data.signature;

              if (!(Object.keys(data).length > 0 && signature !== getSignature(data))) {
                _context.next = 6;
                break;
              }

              throw new Error('Invalid signature for record ' + name);

            case 6:
              Object.keys(currentData).forEach(function (k) {
                if (!data[k] && callbacks[k]) {
                  callbacks[k].forEach(function (callback) {
                    return callback();
                  });
                }
              });
              Object.keys(data).forEach(function (k) {
                if (data[k] !== currentData[k] && callbacks[k]) {
                  callbacks[k].forEach(function (callback) {
                    return callback(data[k]);
                  });
                }
              });
              currentData = data;
              _context.next = 32;
              break;

            case 11:
              _context.prev = 11;
              _context.t0 = _context['catch'](0);
              _iteratorNormalCompletion = true;
              _didIteratorError = false;
              _iteratorError = undefined;
              _context.prev = 16;

              for (_iterator = errbacks[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                errback = _step.value;
                // eslint-disable-line no-restricted-syntax
                errback(_context.t0);
              }
              _context.next = 24;
              break;

            case 20:
              _context.prev = 20;
              _context.t1 = _context['catch'](16);
              _didIteratorError = true;
              _iteratorError = _context.t1;

            case 24:
              _context.prev = 24;
              _context.prev = 25;

              if (!_iteratorNormalCompletion && _iterator.return) {
                _iterator.return();
              }

            case 27:
              _context.prev = 27;

              if (!_didIteratorError) {
                _context.next = 30;
                break;
              }

              throw _iteratorError;

            case 30:
              return _context.finish(27);

            case 31:
              return _context.finish(24);

            case 32:
            case 'end':
              return _context.stop();
          }
        }
      }, _callee, _this, [[0, 11], [16, 20, 24, 32], [25,, 27, 31]]);
    }));

    return function (_x2) {
      return _ref.apply(this, arguments);
    };
  }(), true);
  var subscribe = function subscribe(key, callback, errback) {
    callbacks[key] = callbacks[key] || [];
    callbacks[key].push(callback);
    if (errback) {
      errbacks.add(errback);
    }
  };
  var discard = function () {
    var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
      return _regenerator2.default.wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              if (!record.isDestroyed) {
                _context2.next = 2;
                break;
              }

              return _context2.abrupt('return');

            case 2:
              record.unsubscribe();
              _context2.next = 5;
              return new Promise(function (resolve, reject) {
                record.once('discard', resolve);
                record.once('error', reject);
                record.discard();
              });

            case 5:
            case 'end':
              return _context2.stop();
          }
        }
      }, _callee2, _this);
    }));

    return function discard() {
      return _ref2.apply(this, arguments);
    };
  }();
  var set = function () {
    var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(key, value) {
      var remoteValue, data;
      return _regenerator2.default.wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              _context3.next = 2;
              return readyPromise;

            case 2:
              remoteValue = record.get();

              if (Object.keys(remoteValue).length > 0 && remoteValue.signature !== getSignature(remoteValue)) {
                console.error('Invalid signature for record ' + name + ', clearing.'); // eslint-disable-line no-console
                remoteValue = {};
              }
              data = Object.assign({}, remoteValue, defaultValue, {
                publicKey: pemPublicKey
              });

              data[key] = value;
              data.signature = getSignature(data);
              _context3.next = 9;
              return new Promise(function (resolve, reject) {
                record.set(data, function (errorMessage) {
                  if (errorMessage) {
                    reject(new Error(errorMessage));
                  } else {
                    resolve();
                  }
                });
              });

            case 9:
            case 'end':
              return _context3.stop();
          }
        }
      }, _callee3, _this);
    }));

    return function set(_x3, _x4) {
      return _ref3.apply(this, arguments);
    };
  }();
  return { set: set, subscribe: subscribe, discard: discard };
};

var _deepstream = require('deepstream.io-client-js');

var _deepstream2 = _interopRequireDefault(_deepstream);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }<|endoftext|>


<commit_before>var mysql = require("mysql");

module.exports.getConnection = function() {
    // Test connection health before returning it to caller.
    if ((module.exports.connection) && (module.exports.connection._socket)
  && (module.exports.connection._socket.readable)
	&& (module.exports.connection._socket.writable)) {
        return module.exports.connection;
    }
    console.log(((module.exports.connection) ?
		 "UNHEALTHY SQL CONNECTION; RE" : "") + "CONNECTING TO SQL.");
    var connection = mysql.createConnection({
		database : '', // Enter mysql
 		user     : '', // info
 		password : '', // here
		multipleStatements : true,
	});
    connection.connect(function(err) {
	    if (err) {
		console.log("SQL CONNECT ERROR: " + err);
	    } else {
		console.log("SQL CONNECT SUCCESSFUL.");
	    }
	});
    connection.on("close", function (err) {
	    console.log("SQL CONNECTION CLOSED.");
	});
    connection.on("error", function (err) {
	    console.log("SQL CONNECTION ERROR: " + err);
	});
    module.exports.connection = connection;
    return module.exports.connection;
}

// Open a connection automatically at app startup.
module.exports.getConnection();

// If you've saved this file as database.js, then get and use the
// connection as in the following example:
// var database = require(__dirname + "/database");
// var connection = database.getConnection();
// connection.query(query, function(err, results) {
<commit_msg>Local changes<commit_after><|endoftext|>


<commit_before>/*---------------------------------------------------------------------------
  Copyright 2013 Microsoft Corporation.

  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the file "license.txt" at the root of this distribution.
---------------------------------------------------------------------------*/

define(["../scripts/promise","../scripts/util"], function(Promise,Util) {

var appKey      = "3vj9witefc2z44w";
var root        = "dropbox";
var redirectUri = "https://www.madoko.net/redirect/dropbox";
//var redirectUri = "https://madoko.cloudapp.net/redirect/dropbox";
var contentUrl  = "https://api-content.dropbox.com/1/files/" + root + "/";
var pushUrl     = "https://api-content.dropbox.com/1/files_put/" + root + "/";
var metadataUrl = "https://api.dropbox.com/1/metadata/" + root + "/";
var fileopsUrl  = "https://api.dropbox.com/1/fileops/";
var accountUrl  = "https://api.dropbox.com/1/account/";
var sharesUrl   = "https://api.dropbox.com/1/shares/auto";

var appRoot     = "";

var _access_token = null;
var _username = "";

function getAccessToken() {
  if (!_access_token) {
    _access_token = Util.getCookie("auth_dropbox");
  }
  return _access_token;
}

/* ----------------------------------------------
   Login
---------------------------------------------- */

function login(dontForce) {
  if (getAccessToken()) return Promise.resolved();
  if (dontForce) return Promise.rejected( new Error("dropbox: not logged in") );
  var url = "https://www.dropbox.com/1/oauth2/authorize"
  var params = {
    response_type: "token",
    client_id: appKey,
    redirect_uri:  redirectUri,
    state: Util.generateOAuthState(),
  };
  return Util.openModalPopup(url,params,"oauth",600,600).then( function() {
    if (!getAccessToken()) throw new Error("dropbox login failed");
    return getUserName();
  });
}

function getUserName() {
  if (_username) return Promise.resolved(_username);
  return Util.requestGET( accountUrl + "info", { access_token: getAccessToken() } ).then( function(info) {
    if (typeof info === "string") info = JSON.parse(info);
    _username = info ? info.display_name : "";
    return _username;
  });
}

function logout() {
  Util.setCookie("auth_dropbox","",0);
  _access_token = null;
  _username = "";
}

function chooseOneFile() {
  return new Promise( function(cont) {
    window.Dropbox.choose( {
      success: function(files) {
        if (!files || !files.length || files.length !== 1) cont(new Error("Can only select a single file to open"));
        cont(null, files[0].link );
      },
      cancel: function() {
        cont( new Error("dropbox dialog was canceled") );
      },
      linkType: "direct",
      multiselect: false,
      extensions: [".mdk",".md",".mkdn",".markdown"],
    });
  });
}

function loginAndChooseOneFile() {
  Util.setCookie("dropbox-next","choose",60);
  return login().then( function() {
    Util.setCookie("dropbox-next","",0);
    var err  = Util.getCookie("dropbox-error");
    if (err) {
      throw new Error( decodeURIComponent(err) );
    }
    var link = Util.getCookie("dropbox-choose");
    if (!link) {
      throw new Error( "dropbox: could not read file selection -- try again" );
    }
    return decodeURIComponent(link);
  });
}

/* ----------------------------------------------
  Basic file API
---------------------------------------------- */

function pullFile(fname,binary) {
  var opts = { url: contentUrl + fname, binary: binary };
  return Util.requestGET( opts, { access_token: getAccessToken() });
}

function fileInfo(fname) {
  var url = metadataUrl + fname;
  return Util.requestGET( url, { access_token: getAccessToken() }).then( function(info) {
    return (typeof info === "string" ? JSON.parse(info) : info);
  });
}

function folderInfo(fname) {
  var url = metadataUrl + fname;
  return Util.requestGET( url, { access_token: getAccessToken(), list: true }).then( function(info) {
    return (typeof info === "string" ? JSON.parse(info) : info);
  });
}

function pushFile(fname,content) {
  var url = pushUrl + fname;
  return Util.requestPOST( url, { access_token: getAccessToken() }, content ).then( function(info) {
    if (!info) throw new Error("dropbox: could not push file: " + fname);
    return (typeof info === "string" ? JSON.parse(info) : info);
  });
  //, function(err) {
  //  throw new Error("dropbox: could not push file: " + fname + ": " + err.toString());
  //});
}

function createFolder( dirname ) {
  var url = fileopsUrl + "create_folder";
  return Util.requestPOST( url, {
    access_token: getAccessToken(),
    root: root,
    path: dirname,
  }).then( function(info) {
    return true; // freshly created
  }, function(err) {
    if (err.httpCode === 403) return false;
    throw err;
  });
}

function getShareUrl( fname ) {
  var url = sharesUrl + fname;
  return Util.requestPOST( url, { access_token: getAccessToken(), short_url: false } ).then( function(info) {
    if (typeof info === "string") info = JSON.parse(info);
    return (info.url || null);
  });
}

/* ----------------------------------------------
   Main entry points
---------------------------------------------- */

function openFile() {
  // carefully login so we avoid popup blockers but can still use dropbox's file picker
  var choose = (getAccessToken() ? chooseOneFile : loginAndChooseOneFile);
  return choose().then( function(fileLink) {
    var cap = new RegExp("^https://" + ".*?/view/[^\\/]+/" + appRoot + "(.*)$").exec(fileLink);
    if (!cap) throw (new Error("Can only select files in the " + appRoot + " folder"));
    return cap[1];
  }).then( function(fname) {
    return { remote: new Dropbox(Util.dirname(fname)), docName: Util.basename(fname) };
  });
}

function createAt( folder ) {
  return login().then( function() {
    return new Dropbox(folder);
  });
}

/* ----------------------------------------------
   Remote interface
---------------------------------------------- */

function unpersist(obj) {
  return new Dropbox(obj.folder);
}

function type() {
  return "dropbox";
}

function logo() {
  return "icon-dropbox.png";
}

var Dropbox = (function() {

  function Dropbox( folder ) {
    var self = this;
    self.folder = folder || "";
  }

  Dropbox.prototype.createNewAt = function(folder) {
    return createAt(folder);
  }

  Dropbox.prototype.type = function() {
    return type();
  }

  Dropbox.prototype.logo = function() {
    return logo();
  }

  Dropbox.prototype.getFolder = function() {
    var self = this;
    return self.folder;
  }

  Dropbox.prototype.persist = function() {
    var self = this;
    return { folder: self.folder };
  }

  Dropbox.prototype.fullPath = function(fname) {
    var self = this;
    return Util.combine(self.folder,fname);
  }

  Dropbox.prototype.connect = function(dontForce) {
    return login(dontForce);
  }

  Dropbox.prototype.createSubFolder = function(dirname) {
    var self = this;
    var folder = self.fullPath(dirname);
    return createFolder(folder).then( function(created) {
      return { folder: folder, created: created };
    });
  }

  Dropbox.prototype.pushFile = function( fpath, content ) {
    var self = this;
    return pushFile( self.fullPath(fpath), content ).then( function(info) {
      return new Date(info.modified);
    });
  }

  Dropbox.prototype.pullFile = function( fpath, binary ) {
    var self = this;
    return self.getRemoteTime(fpath).then( function(date) {
      if (!date) return Promise.rejected("file not found: " + fpath);
      return pullFile( self.fullPath(fpath), binary ).then( function(content,req) {
        var file = {
          path: fpath,
          content: content,
          createdTime: date,
        };
        return file;
      });
    });
  }

  Dropbox.prototype.getRemoteTime = function( fpath ) {
    var self = this;
    return fileInfo( self.fullPath(fpath) ).then( function(info) {
      return (info && !info.is_deleted ? new Date(info.modified) : null);
    }, function(err) {
      return null;
    });
  }

  Dropbox.prototype.listing = function( fpath ) {
    var self = this;
    return folderInfo( self.fullPath(fpath) ).then( function(info) {
      return (info ? info.contents : []).map( function(item) {
        item.type = item.is_dir ? "folder" : "file";
        item.isShared = item.is_dir && item.icon==="folder_user";
        return item;
      });
    });
  }

  Dropbox.prototype.connected = function() {
    return (getAccessToken() != null);
  }

  Dropbox.prototype.login = function() {
    return login();
  }

  Dropbox.prototype.logout = function() {
    return logout();
  }

  Dropbox.prototype.getUserName = function() {
    var self = this;
    if (!self.connected()) return Promise.resolved(null);
    return getUserName();
  }

  Dropbox.prototype.getShareUrl = function(fname) {
    var self = this;
    return getShareUrl( self.fullPath(fname) );
  };

  return Dropbox;
})();

return {
  openFile: openFile,
  createAt: createAt,
  login: login,
  logout: logout,
  unpersist: unpersist,
  type: type,
  logo: logo,
  Dropbox: Dropbox,
}

});<commit_msg>Fix shares url creation dropbox on IE.<commit_after>/*---------------------------------------------------------------------------
  Copyright 2013 Microsoft Corporation.

  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the file "license.txt" at the root of this distribution.
---------------------------------------------------------------------------*/

define(["../scripts/promise","../scripts/util"], function(Promise,Util) {

var appKey      = "3vj9witefc2z44w";
var root        = "dropbox";
var redirectUri = "https://www.madoko.net/redirect/dropbox";
//var redirectUri = "https://madoko.cloudapp.net/redirect/dropbox";
var contentUrl  = "https://api-content.dropbox.com/1/files/" + root + "/";
var pushUrl     = "https://api-content.dropbox.com/1/files_put/" + root + "/";
var metadataUrl = "https://api.dropbox.com/1/metadata/" + root + "/";
var fileopsUrl  = "https://api.dropbox.com/1/fileops/";
var accountUrl  = "https://api.dropbox.com/1/account/";
var sharesUrl   = "https://api.dropbox.com/1/shares/" + root + "/";

var appRoot     = "";

var _access_token = null;
var _username = "";

function getAccessToken() {
  if (!_access_token) {
    _access_token = Util.getCookie("auth_dropbox");
  }
  return _access_token;
}

/* ----------------------------------------------
   Login
---------------------------------------------- */

function login(dontForce) {
  if (getAccessToken()) return Promise.resolved();
  if (dontForce) return Promise.rejected( new Error("dropbox: not logged in") );
  var url = "https://www.dropbox.com/1/oauth2/authorize"
  var params = {
    response_type: "token",
    client_id: appKey,
    redirect_uri:  redirectUri,
    state: Util.generateOAuthState(),
  };
  return Util.openModalPopup(url,params,"oauth",600,600).then( function() {
    if (!getAccessToken()) throw new Error("dropbox login failed");
    return getUserName();
  });
}

function getUserName() {
  if (_username) return Promise.resolved(_username);
  return Util.requestGET( accountUrl + "info", { access_token: getAccessToken() } ).then( function(info) {
    if (typeof info === "string") info = JSON.parse(info);
    _username = info ? info.display_name : "";
    return _username;
  });
}

function logout() {
  Util.setCookie("auth_dropbox","",0);
  _access_token = null;
  _username = "";
}

function chooseOneFile() {
  return new Promise( function(cont) {
    window.Dropbox.choose( {
      success: function(files) {
        if (!files || !files.length || files.length !== 1) cont(new Error("Can only select a single file to open"));
        cont(null, files[0].link );
      },
      cancel: function() {
        cont( new Error("dropbox dialog was canceled") );
      },
      linkType: "direct",
      multiselect: false,
      extensions: [".mdk",".md",".mkdn",".markdown"],
    });
  });
}

function loginAndChooseOneFile() {
  Util.setCookie("dropbox-next","choose",60);
  return login().then( function() {
    Util.setCookie("dropbox-next","",0);
    var err  = Util.getCookie("dropbox-error");
    if (err) {
      throw new Error( decodeURIComponent(err) );
    }
    var link = Util.getCookie("dropbox-choose");
    if (!link) {
      throw new Error( "dropbox: could not read file selection -- try again" );
    }
    return decodeURIComponent(link);
  });
}

/* ----------------------------------------------
  Basic file API
---------------------------------------------- */

function pullFile(fname,binary) {
  var opts = { url: contentUrl + fname, binary: binary };
  return Util.requestGET( opts, { access_token: getAccessToken() });
}

function fileInfo(fname) {
  var url = metadataUrl + fname;
  return Util.requestGET( url, { access_token: getAccessToken() }).then( function(info) {
    return (typeof info === "string" ? JSON.parse(info) : info);
  });
}

function folderInfo(fname) {
  var url = metadataUrl + fname;
  return Util.requestGET( url, { access_token: getAccessToken(), list: true }).then( function(info) {
    return (typeof info === "string" ? JSON.parse(info) : info);
  });
}

function pushFile(fname,content) {
  var url = pushUrl + fname;
  return Util.requestPOST( url, { access_token: getAccessToken() }, content ).then( function(info) {
    if (!info) throw new Error("dropbox: could not push file: " + fname);
    return (typeof info === "string" ? JSON.parse(info) : info);
  });
  //, function(err) {
  //  throw new Error("dropbox: could not push file: " + fname + ": " + err.toString());
  //});
}

function createFolder( dirname ) {
  var url = fileopsUrl + "create_folder";
  return Util.requestPOST( url, {
    access_token: getAccessToken(),
    root: root,
    path: dirname,
  }).then( function(info) {
    return true; // freshly created
  }, function(err) {
    if (err.httpCode === 403) return false;
    throw err;
  });
}

function getShareUrl( fname ) {
  var url = Util.combine(sharesUrl,fname);
  return Util.requestPOST( url, { access_token: getAccessToken(), short_url: false } ).then( function(info) {
    if (typeof info === "string") info = JSON.parse(info);
    return (info.url || null);
  });
}

/* ----------------------------------------------
   Main entry points
---------------------------------------------- */

function openFile() {
  // carefully login so we avoid popup blockers but can still use dropbox's file picker
  var choose = (getAccessToken() ? chooseOneFile : loginAndChooseOneFile);
  return choose().then( function(fileLink) {
    var cap = new RegExp("^https://" + ".*?/view/[^\\/]+/" + appRoot + "(.*)$").exec(fileLink);
    if (!cap) throw (new Error("Can only select files in the " + appRoot + " folder"));
    return cap[1];
  }).then( function(fname) {
    return { remote: new Dropbox(Util.dirname(fname)), docName: Util.basename(fname) };
  });
}

function createAt( folder ) {
  return login().then( function() {
    return new Dropbox(folder);
  });
}

/* ----------------------------------------------
   Remote interface
---------------------------------------------- */

function unpersist(obj) {
  return new Dropbox(obj.folder);
}

function type() {
  return "dropbox";
}

function logo() {
  return "icon-dropbox.png";
}

var Dropbox = (function() {

  function Dropbox( folder ) {
    var self = this;
    self.folder = folder || "";
  }

  Dropbox.prototype.createNewAt = function(folder) {
    return createAt(folder);
  }

  Dropbox.prototype.type = function() {
    return type();
  }

  Dropbox.prototype.logo = function() {
    return logo();
  }

  Dropbox.prototype.getFolder = function() {
    var self = this;
    return self.folder;
  }

  Dropbox.prototype.persist = function() {
    var self = this;
    return { folder: self.folder };
  }

  Dropbox.prototype.fullPath = function(fname) {
    var self = this;
    return Util.combine(self.folder,fname);
  }

  Dropbox.prototype.connect = function(dontForce) {
    return login(dontForce);
  }

  Dropbox.prototype.createSubFolder = function(dirname) {
    var self = this;
    var folder = self.fullPath(dirname);
    return createFolder(folder).then( function(created) {
      return { folder: folder, created: created };
    });
  }

  Dropbox.prototype.pushFile = function( fpath, content ) {
    var self = this;
    return pushFile( self.fullPath(fpath), content ).then( function(info) {
      return new Date(info.modified);
    });
  }

  Dropbox.prototype.pullFile = function( fpath, binary ) {
    var self = this;
    return self.getRemoteTime(fpath).then( function(date) {
      if (!date) return Promise.rejected("file not found: " + fpath);
      return pullFile( self.fullPath(fpath), binary ).then( function(content,req) {
        var file = {
          path: fpath,
          content: content,
          createdTime: date,
        };
        return file;
      });
    });
  }

  Dropbox.prototype.getRemoteTime = function( fpath ) {
    var self = this;
    return fileInfo( self.fullPath(fpath) ).then( function(info) {
      return (info && !info.is_deleted ? new Date(info.modified) : null);
    }, function(err) {
      return null;
    });
  }

  Dropbox.prototype.listing = function( fpath ) {
    var self = this;
    return folderInfo( self.fullPath(fpath) ).then( function(info) {
      return (info ? info.contents : []).map( function(item) {
        item.type = item.is_dir ? "folder" : "file";
        item.isShared = item.is_dir && item.icon==="folder_user";
        return item;
      });
    });
  }

  Dropbox.prototype.connected = function() {
    return (getAccessToken() != null);
  }

  Dropbox.prototype.login = function() {
    return login();
  }

  Dropbox.prototype.logout = function() {
    return logout();
  }

  Dropbox.prototype.getUserName = function() {
    var self = this;
    if (!self.connected()) return Promise.resolved(null);
    return getUserName();
  }

  Dropbox.prototype.getShareUrl = function(fname) {
    var self = this;
    return getShareUrl( self.fullPath(fname) );
  };

  return Dropbox;
})();

return {
  openFile: openFile,
  createAt: createAt,
  login: login,
  logout: logout,
  unpersist: unpersist,
  type: type,
  logo: logo,
  Dropbox: Dropbox,
}

});<|endoftext|>