<commit_before>/***
 * Copyright (c) 2015 <NAME> (@localnerve), LocalNerve LLC
 * Copyrights licensed under the BSD License. See the accompanying LICENSE file for terms.
 *
 * Module to contain sync operations.
 */
/* global Blob, Promise, Request, Response, fetch, self */
'use strict';

var toolbox = require('sw-toolbox');
var idb = require('../utils/idb');
var debug = require('../utils/debug')('sync');
var requestLib = require('../utils/requests');
var initApis = require('../utils/db').init({ key: 'apis' });
var filters = require('./filters');
var serviceable = require('./serviceable');

/***
 * The maximum number of times a single request can attempt synchronization.
 * This is incremented on a request when a synchronization attempt fails.
 * @see serviceAllRequests
 */
var MAX_RETRIES = 3;

/**
 * Defer a request until later by storing it in IndexedDB.
 * This is called if the fetch fails.
 *
 * NOTE:
 * 1. Stores the old csrf token in the url. Replaced when serviced later.
 * @see serviceAllRequests
 *
 * @param {String} apiPath - The key used to service the requets in proper xhrContext.
 * @param {Object} request - A Request object to use to make the post request.
 * @returns {Promise} Resolves to a Response with a status of 203 or 400.
 */
function deferRequest (apiPath, request) {
  // TODO: Update this test to ensure permissions have been obtained.
  var hasSync = !!self.registration.sync;

  return requestLib.dehydrateRequest(request, 'json')
  .then(function (dehydratedRequest) {
    var timestamp = Date.now().toString();
    var fallback = filters.getFallback(dehydratedRequest.body, true) || {};

    // Store the timestamp with the value for easier management in serviceAllRequests.
    dehydratedRequest.timestamp = timestamp;

    // Store the apiPath with the value to allow the request to be serviced
    // in the proper xhrContext in serviceAllRequests.
    dehydratedRequest.apiPath = apiPath;

    // Keep the fallback processing directives at the top level.
    dehydratedRequest.fallback = fallback;

    // Add it to IndexedDB.
    return idb.put(idb.stores.requests, timestamp, dehydratedRequest)
    .then(function () {
      return new Response('deferred', {
        // If no sync and user replayable, show user 400 failure.
        //   TODO (#15): However, replay request on next init.
        status: hasSync || !fallback.userReplayable ? 203 : 400
        // Remember, the user can replay their own requests, too.
      });
    });
  });
}

/**
 * Maintain deferred requests.
 *
 * Passes through the given Response, but maintains the deferred requests as
 * a side-effect.
 *
 * Intended to be used on successful network fetch (as a successHandler) to
 * manually remove deferred requests to avoid unintended synchronization.
 *
 * Use case: A request succeeds that renders prior deferred requests
 *  illegitimate/unwarranted/dangerous/etc.
 *
 * @param {Request|String} req - ignored.
 * @param {Response} res - passed through on success.
 * @param {Request|String} reqToCache - A clone of the Request that succeeded
 * on the network that would be used for caching and contains a fallback object.
 * @returns {Promise} Resolves to the Response on success.
 */
function maintainRequests (req, res, reqToCache) {
  return idb.all(idb.stores.requests).then(function (dehydratedRequests) {
    var request = typeof reqCache === 'string' ?
      new Request(reqToCache) : reqToCache.clone();

    return request.json().then(function (body) {
      return serviceable.pruneRequestsByPolicy(
        dehydratedRequests,
        filters.getFallback(body)
      );
    });
  }).then(function () {
    return res;
  });
}

/**
 * Remove a fallback object (if found) from request and clone.
 *
 * @param {Object} options - Request init options to create with.
 * @param {Request} request - The request to clone.
 * @returns {Promise} Resolves to a request clone with options and
 * fallback object removed.
 */
function removeFallback (options, request) {
  var req = request.clone();

  return req.json().then(function (body) {<commit_msg>remove invalid string input option<commit_after>/***
 * Copyright (c) 2015 <NAME> (@localnerve), LocalNerve LLC
 * Copyrights licensed under the BSD License. See the accompanying LICENSE file for terms.
 *
 * Module to contain sync operations.
 */
/* global Blob, Promise, Request, Response, fetch, self */
'use strict';

var toolbox = require('sw-toolbox');
var idb = require('../utils/idb');
var debug = require('../utils/debug')('sync');
var requestLib = require('../utils/requests');
var initApis = require('../utils/db').init({ key: 'apis' });
var filters = require('./filters');
var serviceable = require('./serviceable');

/***
 * The maximum number of times a single request can attempt synchronization.
 * This is incremented on a request when a synchronization attempt fails.
 * @see serviceAllRequests
 */
var MAX_RETRIES = 3;

/**
 * Defer a request until later by storing it in IndexedDB.
 * This is called if the fetch fails.
 *
 * NOTE:
 * 1. Stores the old csrf token in the url. Replaced when serviced later.
 * @see serviceAllRequests
 *
 * @param {String} apiPath - The key used to service the requets in proper xhrContext.
 * @param {Object} request - A Request object to use to make the post request.
 * @returns {Promise} Resolves to a Response with a status of 203 or 400.
 */
function deferRequest (apiPath, request) {
  // TODO: Update this test to ensure permissions have been obtained.
  var hasSync = !!self.registration.sync;

  return requestLib.dehydrateRequest(request, 'json')
  .then(function (dehydratedRequest) {
    var timestamp = Date.now().toString();
    var fallback = filters.getFallback(dehydratedRequest.body, true) || {};

    // Store the timestamp with the value for easier management in serviceAllRequests.
    dehydratedRequest.timestamp = timestamp;

    // Store the apiPath with the value to allow the request to be serviced
    // in the proper xhrContext in serviceAllRequests.
    dehydratedRequest.apiPath = apiPath;

    // Keep the fallback processing directives at the top level.
    dehydratedRequest.fallback = fallback;

    // Add it to IndexedDB.
    return idb.put(idb.stores.requests, timestamp, dehydratedRequest)
    .then(function () {
      return new Response('deferred', {
        // If no sync and user replayable, show user 400 failure.
        //   TODO (#15): However, replay request on next init.
        status: hasSync || !fallback.userReplayable ? 203 : 400
        // Remember, the user can replay their own requests, too.
      });
    });
  });
}

/**
 * Maintain deferred requests.
 *
 * Passes through the given Response, but maintains the deferred requests as
 * a side-effect.
 *
 * Intended to be used on successful network fetch (as a successHandler) to
 * manually remove deferred requests to avoid unintended synchronization.
 *
 * Use case: A request succeeds that renders prior deferred requests
 *  illegitimate/unwarranted/dangerous/etc.
 *
 * @param {Request} req - ignored.
 * @param {Response} res - passed through on success.
 * @param {Request} reqToCache - A clone of the Request that succeeded
 * on the network that would be used for caching and contains a fallback object.
 * @returns {Promise} Resolves to the Response on success.
 */
function maintainRequests (req, res, reqToCache) {
  return idb.all(idb.stores.requests).then(function (dehydratedRequests) {
    var request = reqToCache.clone();

    return request.json().then(function (body) {
      return serviceable.pruneRequestsByPolicy(
        dehydratedRequests,
        filters.getFallback(body)
      );
    });
  }).then(function () {
    return res;
  });
}

/**
 * Remove a fallback object (if found) from request and clone.
 *
 * @param {Object} options - Request init options to create with.
 * @param {Request} request - The request to clone.
 * @returns {Promise} Resolves to a request clone with options and
 * fallback object removed.
 */
function removeFallback (options, request) {
  var req = request.clone();

  return req.json().then(function (body) {
{'fraction_non_alphanumeric': 0.10644843711543195, 'fraction_numerical': 0.005660841742554762, 'mean_word_length': 3.5376884422110555, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6516145', 'n_tokens_mistral': 2333, 'n_tokens_neox': 2224, 'n_words': 879}