<commit_before>/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

function PanoramioController($scope,$injector){
   console.log('$PanoramioController init');

   $injector.invoke(PhotolocationController, this, {$scope: $scope});

   $scope.myRequest = {
        'tag': 'city',
        'rect': {'sw': {'lat':49.5, 'lng': 10.7},'ne': {'lat':49.7, 'lng': 11.3}},
    };

    $scope.Tags = [
        'sunset',
        'beaches',
        'panorama',
        'mountains',
        'church',
        'urban',
        'mountain',
        'playas',
        'best',
        'castle'
    ];

    $scope.photo_options = {
        'width': 300,
        'height': 256,
        'croppedPhotos':true
    };

    var wapiblock = null;
    var widget = null;
    var WIDGET_ANIMATION_TIME = 300;
    $scope.InitPhotoWidget = function()
    {
        if(wapiblock !== null)
        {
            return null;
        }
        if(widget!== null)
        {
            return null;
        }

        console.log("Initialize PanoramioWidget");

        wapiblock = document.getElementById('wapiblock');
        widget = new panoramio.PhotoWidget(wapiblock, $scope.myRequest, $scope.photo_options);
        widget.setPosition(0);

        panoramio.events.listen( widget, panoramio.events.EventType.PHOTO_CHANGED,
                                    function(e) { $scope.HandlePhotoChanged(e); });

        google.maps.event.addListener($scope.PhotoPosition.Marker, 'click', function() {
            $scope.DisplayPhotoWidgetTemporal(4000);
        });
        google.maps.event.addListener($scope.map,'bounds_changed',function(){
            console.log("PanoramioController: HandleMapBoundsChanged");
           var bounds = $scope.GetBounds();
           var ne = bounds.getNorthEast();
           var sw = bounds.getSouthWest();
           $scope.myRequest.rect = {'sw': {'lat':sw.lat(), 'lng': sw.lng()},
                                    'ne': {'lat':ne.lat(), 'lng': ne.lng()}};
           $scope.HanldeRequestChanged();
        });
        $(wapiblock).hide().delay(1000).show();
        $scope.DisplayPhotoWidgetTemporal(4000);
    };
    $scope.DisplayPhotoWidget = function(){
        return $(wapiblock).show(WIDGET_ANIMATION_TIME);
    };
    $scope.HidePhotoWidget = function()
    {
        return $(wapiblock).hide(WIDGET_ANIMATION_TIME);
    };
    $scope.DisplayPhotoWidgetTemporal = function(timeOut)
    {
        var t_delay = timeOut;
        if(typeof t_delay === "undefined")
        {
            t_delay = 3000;
        }
        $(wapiblock).show(WIDGET_ANIMATION_TIME)
                .delay(timeOut)
                .hide(WIDGET_ANIMATION_TIME);
    };
    $scope.HandlePhotoChanged = function()
    {
        console.log("Panoramio PhotoChanged");
        var img = widget.getPhoto();
        if(img !== null){
            var pos = img.getPosition();
            $scope.$broadcast("PhotoPositionChanged", {coords:{latitude: pos.lat,longitude: pos.lng}});
        }
    };
    $scope.HanldeRequestChanged = function()
    {
        if(widget === null){
            console.log("Error PanoramioController: widget not initialized!")
            return;
        }
        widget.setRequest($scope.myRequest);
        widget.setPosition(0);
    };

    console.log("$PanoramioController init");
    $scope.InitPhotoWidget();
};
<commit_msg>Adapted tagging of photos<commit_after>/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

function PanoramioController($scope,$injector){
   console.log('$PanoramioController init');

   $injector.invoke(PhotolocationController, this, {$scope: $scope});

   $scope.myRequest = {
        'rect': {'sw': {'lat':49.5, 'lng': 10.7},'ne': {'lat':49.7, 'lng': 11.3}},
    };

    $scope.Tags = [
        'sunset',
        'beaches',
        'panorama',
        'mountains',
        'church',
        'urban',
        'mountain',
        'playas',
        'best',
        'castle'
    ];

    $scope.photo_options = {
        'width': 300,
        'height': 256,
        'croppedPhotos':true
    };

    var wapiblock = null;
    var widget = null;
    var WIDGET_ANIMATION_TIME = 300;
    $scope.InitPhotoWidget = function()
    {
        if(wapiblock !== null)
        {
            return null;
        }
        if(widget!== null)
        {
            return null;
        }

        console.log("Initialize PanoramioWidget");

        wapiblock = document.getElementById('wapiblock');
        widget = new panoramio.PhotoWidget(wapiblock, $scope.myRequest, $scope.photo_options);
        widget.setPosition(0);

        panoramio.events.listen( widget, panoramio.events.EventType.PHOTO_CHANGED,
                                    function(e) { $scope.HandlePhotoChanged(e); });

        google.maps.event.addListener($scope.PhotoPosition.Marker, 'click', function() {
            $scope.DisplayPhotoWidgetTemporal(4000);
        });
        google.maps.event.addListener($scope.map,'bounds_changed',function(){
            console.log("PanoramioController: HandleMapBoundsChanged");
           var bounds = $scope.GetBounds();
           var ne = bounds.getNorthEast();
           var sw = bounds.getSouthWest();
           $scope.myRequest.rect = {'sw': {'lat':sw.lat(), 'lng': sw.lng()},
                                    'ne': {'lat':ne.lat(), 'lng': ne.lng()}};
           $scope.HanldeRequestChanged();
        });
        $(wapiblock).hide().delay(1000).show();
        $scope.DisplayPhotoWidgetTemporal(4000);
    };
    $scope.DisplayPhotoWidget = function(){
        return $(wapiblock).show(WIDGET_ANIMATION_TIME);
    };
    $scope.HidePhotoWidget = function()
    {
        return $(wapiblock).hide(WIDGET_ANIMATION_TIME);
    };
    $scope.DisplayPhotoWidgetTemporal = function(timeOut)
    {
        var t_delay = timeOut;
        if(typeof t_delay === "undefined")
        {
            t_delay = 3000;
        }
        $(wapiblock).show(WIDGET_ANIMATION_TIME)
                .delay(timeOut)
                .hide(WIDGET_ANIMATION_TIME);
    };
    $scope.HandlePhotoChanged = function()
    {
        console.log("Panoramio PhotoChanged");
        var img = widget.getPhoto();
        if(img !== null){
            var pos = img.getPosition();
            $scope.$broadcast("PhotoPositionChanged", {coords:{latitude: pos.lat,longitude: pos.lng}});
        }
    };
    $scope.HanldeRequestChanged = function()
    {
        if(widget === null){
            console.log("Error PanoramioController: widget not initialized!")
            return;
        }
        widget.setRequest($scope.myRequest);
        widget.setPosition(0);
    };

    console.log("$PanoramioController init");
    $scope.InitPhotoWidget();
};
<|endoftext|>


<commit_before>import React from 'react';
import autoBind from 'react-autobind';
import TagsInput from 'react-tagsinput';
import {cleanupTags} from 'js/assetUtils';

const DEFAULT_PLACEHOLDER = t('Type and confirm with ENTER');
const TAGS_SEPARATOR = ',';

/**
 * This component is a wrapper around 3rd party react-tagsinput to allow for
 * common settings to be reused in a better way.
 *
 * @prop {string} tags a comma-separated list of tags (the asset keeps it that way)
 * @prop {callback} onChange - returns stringified comma-separated new tags string
 * @prop {string} [label] optional title
 * @prop {string} [placeholder] optional as default is provided
 */
class KoboTagsInput extends React.Component {
  constructor(props) {
    super(props);
    autoBind(this);
  }

  onChange(tags) {
    const cleanTags = cleanupTags(tags);
    this.props.onChange(cleanTags.join(TAGS_SEPARATOR));
  }

  // splits pasted text by TAGS_SEPARATOR and trims all white space
  pasteSplit(data) {
    return data.split(TAGS_SEPARATOR).map((tag) => {return tag.trim();});
  }

  render() {
    const inputProps = {
      placeholder: this.props.placeholder || DEFAULT_PLACEHOLDER,
    };

    if (this.props.label) {
      // generate a unique id for the input
      inputProps.id = String(encodeURI(this.props.label) + '_' + Date.now()).toLowerCase();
    }

    let tagsArray = [];
    if (typeof this.props.tags === 'string' && this.props.tags.length >= 1) {
      tagsArray = this.props.tags.split(TAGS_SEPARATOR);
    }

    return (

        {this.props.label &&

            {this.props.label}

        }

        <TagsInput
          value={tagsArray}
          onChange={this.onChange}
          inputProps={inputProps}
          onlyUnique
          addOnBlur
          addOnPaste
          pasteSplit={this.pasteSplit}
        />

    );
  }
}

export default KoboTagsInput;
<commit_msg>make kobotagsinput produce unique values only<commit_after>import React from 'react';
import autoBind from 'react-autobind';
import TagsInput from 'react-tagsinput';
import {cleanupTags} from 'js/assetUtils';

const DEFAULT_PLACEHOLDER = t('Type and confirm with ENTER');
const TAGS_SEPARATOR = ',';

/**
 * This component is a wrapper around 3rd party react-tagsinput to allow for
 * common settings to be reused in a better way.
 *
 * @prop {string} tags a comma-separated list of tags (the asset keeps it that way)
 * @prop {callback} onChange - returns stringified comma-separated new tags string
 * @prop {string} [label] optional title
 * @prop {string} [placeholder] optional as default is provided
 */
class KoboTagsInput extends React.Component {
  constructor(props) {
    super(props);
    autoBind(this);
  }

  onChange(tags) {
    // make sure to split all multiple tags added (i.e. when users types in few
    // tags at once separated by TAGS_SEPARATOR)
    let cleanTags = tags.join(TAGS_SEPARATOR).split(TAGS_SEPARATOR);
    // we then make sure the list contains only unique values and cleaned up
    cleanTags = Array.from(new Set(cleanupTags(cleanTags)));
    this.props.onChange(cleanTags.join(TAGS_SEPARATOR));
  }

  // splits pasted text by TAGS_SEPARATOR and trims all white space
  pasteSplit(data) {
    return data.split(TAGS_SEPARATOR).map((tag) => {return tag.trim();});
  }

  render() {
    const inputProps = {
      placeholder: this.props.placeholder || DEFAULT_PLACEHOLDER,
    };

    if (this.props.label) {
      // generate a unique id for the input
      inputProps.id = String(encodeURI(this.props.label) + '_' + Date.now()).toLowerCase();
    }

    let tagsArray = [];
    if (typeof this.props.tags === 'string' && this.props.tags.length >= 1) {
      tagsArray = this.props.tags.split(TAGS_SEPARATOR);
    }

    return (

        {this.props.label &&

            {this.props.label}

        }

        <TagsInput
          value={tagsArray}
          onChange={this.onChange}
          inputProps={inputProps}
          onlyUnique
          addOnBlur
          addOnPaste
          pasteSplit={this.pasteSplit}
        />

    );
  }
}

export default KoboTagsInput;
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow strict-local
 * @format
 */

// flowlint ambiguous-object-type:error

'use strict';

const RelayModernRecord = require('./RelayModernRecord');

const recycleNodesInto = require('../util/recycleNodesInto');

const {generateClientID} = require('./ClientID');
const {
  RELAY_RESOLVER_VALUE_KEY,
  RELAY_RESOLVER_INVALIDATION_KEY,
  RELAY_RESOLVER_INPUTS_KEY,
  RELAY_RESOLVER_READER_SELECTOR_KEY,
  getStorageKey,
} = require('./RelayStoreUtils');

import type {ReaderRelayResolver} from '../util/ReaderNode';
import type {DataID, Variables} from '../util/RelayRuntimeTypes';
import type {
  MutableRecordSource,
  Record,
  SingularReaderSelector,
} from './RelayStoreTypes';

type ResolverID = string;

type EvaluationResult<T> = {|
  resolverResult: T,
  fragmentValue: {...},
  resolverID: ResolverID,
  seenRecordIDs: Set<DataID>,
  readerSelector: SingularReaderSelector,
|};

export interface ResolverCache {
  readFromCacheOrEvaluate<T>(
    record: Record,
    field: ReaderRelayResolver,
    variables: Variables,
    evaluate: () => EvaluationResult<T>,
    getDataForResolverFragment: (SingularReaderSelector) => mixed,
  ): [T /* Answer */, ?DataID /* Seen record */];
  invalidateDataIDs(
    updatedDataIDs: Set<DataID>, // Mutated in place
  ): void;
}

// $FlowFixMe[unclear-type] - will always be empty
const emptySet: $ReadOnlySet<any> = new Set();

class NoopResolverCache implements ResolverCache {
  readFromCacheOrEvaluate<T>(
    record: Record,
    field: ReaderRelayResolver,
    variables: Variables,
    evaluate: () => EvaluationResult<T>,
    getDataForResolverFragment: SingularReaderSelector => mixed,
  ): [T /* Answer */, ?DataID /* Seen record */] {
    return [evaluate().resolverResult, undefined];
  }
  invalidateDataIDs(updatedDataIDs: Set<DataID>): void {}
}

function addDependencyEdge(edges, from, to): void {
  let set = edges.get(from);
  if (!set) {
    set = new Set();
    edges.set(from, set);
  }
  set.add(to);
}

class RecordResolverCache implements ResolverCache {
  _resolverIDToRecordIDs: Map<ResolverID, Set<DataID>>;
  _recordIDToResolverIDs: Map<DataID, Set<ResolverID>>;

  _getRecordSource: () => MutableRecordSource;

  constructor(getRecordSource: () => MutableRecordSource) {
    this._resolverIDToRecordIDs = new Map();
    this._recordIDToResolverIDs = new Map();
    this._getRecordSource = getRecordSource;
  }

  readFromCacheOrEvaluate<T>(
    record: Record,
    field: ReaderRelayResolver,
    variables: Variables,
    evaluate: () => EvaluationResult<T>,
    getDataForResolverFragment: SingularReaderSelector => mixed,
  ): [T /* Answer */, ?DataID /* Seen record */] {
    const recordSource = this._getRecordSource();
    const recordID = RelayModernRecord.getDataID(record);

    const storageKey = getStorageKey(field, variables);
    let linkedID = RelayModernRecord.getLinkedRecordID(record, storageKey);
    let linkedRecord = linkedID == null ? null : recordSource.get(linkedID);
    if (
      linkedRecord == null ||
      this._isInvalid(linkedRecord, getDataForResolverFragment)
    ) {
      // Cache miss; evaluate the selector and store the result in a new record:
      linkedID = linkedID ?? generateClientID(recordID, storageKey);
      linkedRecord = RelayModernRecord.create(linkedID, '__RELAY_RESOLVER__');

      const evaluationResult = evaluate();
      RelayModernRecord.setValue(
        linkedRecord,
        RELAY_RESOLVER_VALUE_KEY,
        evaluationResult.resolverResult,
      );
      RelayModernRecord.setValue(
        linkedRecord,
        RELAY_RESOLVER_INPUTS_KEY,
        evaluationResult.fragmentValue,
      );
      RelayModernRecord.setValue(
        linkedRecord,
        RELAY_RESOLVER_READER_SELECTOR_KEY,
        evaluationResult.readerSelector,
      );
      recordSource.set(linkedID, linkedRecord);

      // Link the resolver value record to the resolver field of the record being read:
      const nextRecord = RelayModernRecord.clone(record);
      RelayModernRecord.setLinkedRecordID(nextRecord, storageKey, linkedID);
      recordSource.set(RelayModernRecord.getDataID(nextRecord), nextRecord);

      // Put records observed by the resolver into the dependency graph:
      const resolverID = evaluationResult.resolverID;
      addDependencyEdge(this._resolverIDToRecordIDs, resolverID, linkedID);
      addDependencyEdge(this._recordIDToResolverIDs, recordID, resolverID);
      for (const seenRecordID of evaluationResult.seenRecordIDs) {
        addDependencyEdge(
          this._recordIDToResolverIDs,
          seenRecordID,
          resolverID,
        );
      }
    }

    // $FlowFixMe[incompatible-type] - will always be empty
    const answer: T = linkedRecord[RELAY_RESOLVER_VALUE_KEY];
    return [answer, linkedID];
  }

  invalidateDataIDs(
    updatedDataIDs: Set<DataID>, // Mutated in place
  ): void {
    const recordSource = this._getRecordSource();
    const visited: Set<string> = new Set();
    const recordsToVisit = Array.from(updatedDataIDs);
    while (recordsToVisit.length) {
      const recordID = recordsToVisit.pop();
      updatedDataIDs.add(recordID);
      for (const fragment of this._recordIDToResolverIDs.get(recordID) ??
        emptySet) {
        if (!visited.has(fragment)) {
          for (const anotherRecordID of this._resolverIDToRecordIDs.get(
            fragment,
          ) ?? emptySet) {
            this._markInvalidatedResolverRecord(
              anotherRecordID,
              recordSource,
              updatedDataIDs,
            );
            if (!visited.has(anotherRecordID)) {
              recordsToVisit.push(anotherRecordID);
            }
          }
        }
      }
    }
  }

  _markInvalidatedResolverRecord(
    dataID: DataID,
    recordSource: MutableRecordSource, // Written to
    updatedDataIDs: Set<DataID>, // Mutated in place
  ) {
    const record = recordSource.get(dataID);
    if (!record) {
      return; // FIXME log? throw?
    }
    const nextRecord = RelayModernRecord.clone(record);
    RelayModernRecord.setValue(
      nextRecord,
      RELAY_RESOLVER_INVALIDATION_KEY,
      true,
    );
    recordSource.set(dataID, nextRecord);
  }

  _isInvalid(
    record: Record,
    getDataForResolverFragment: SingularReaderSelector => mixed,
  ): boolean {
    if (!RelayModernRecord.getValue(record, RELAY_RESOLVER_INVALIDATION_KEY)) {
      return false;
    }
    const originalInputs = RelayModernRecord.getValue(
      record,
      RELAY_RESOLVER_INPUTS_KEY,
    );
    // $FlowFixMe[incompatible-type] - storing values in records is not typed
    const readerSelector: ?SingularReaderSelector = RelayModernRecord.getValue(
      record,
      RELAY_RESOLVER_READER_SELECTOR_KEY,
    );
    if (originalInputs == null || readerSelector == null) {
      return true; // FIXME log? throw?
    }
    const latestValues = getDataForResolverFragment(readerSelector);
    const recycled = recycleNodesInto(originalInputs, latestValues);
    if (recycled !== originalInputs) {
      return true;
    }
    return false;
  }
}

module.exports = {
  NoopResolverCache,
  RecordResolverCache,
};
<commit_msg>Log error conditions<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow strict-local
 * @format
 */

// flowlint ambiguous-object-type:error

'use strict';

const RelayModernRecord = require('./RelayModernRecord');

const recycleNodesInto = require('../util/recycleNodesInto');
const warning = require('warning');

const {generateClientID} = require('./ClientID');
const {
  RELAY_RESOLVER_VALUE_KEY,
  RELAY_RESOLVER_INVALIDATION_KEY,
  RELAY_RESOLVER_INPUTS_KEY,
  RELAY_RESOLVER_READER_SELECTOR_KEY,
  getStorageKey,
} = require('./RelayStoreUtils');

import type {ReaderRelayResolver} from '../util/ReaderNode';
import type {DataID, Variables} from '../util/RelayRuntimeTypes';
import type {
  MutableRecordSource,
  Record,
  SingularReaderSelector,
} from './RelayStoreTypes';

type ResolverID = string;

type EvaluationResult<T> = {|
  resolverResult: T,
  fragmentValue: {...},
  resolverID: ResolverID,
  seenRecordIDs: Set<DataID>,
  readerSelector: SingularReaderSelector,
|};

export interface ResolverCache {
  readFromCacheOrEvaluate<T>(
    record: Record,
    field: ReaderRelayResolver,
    variables: Variables,
    evaluate: () => EvaluationResult<T>,
    getDataForResolverFragment: (SingularReaderSelector) => mixed,
  ): [T /* Answer */, ?DataID /* Seen record */];
  invalidateDataIDs(
    updatedDataIDs: Set<DataID>, // Mutated in place
  ): void;
}

// $FlowFixMe[unclear-type] - will always be empty
const emptySet: $ReadOnlySet<any> = new Set();

class NoopResolverCache implements ResolverCache {
  readFromCacheOrEvaluate<T>(
    record: Record,
    field: ReaderRelayResolver,
    variables: Variables,
    evaluate: () => EvaluationResult<T>,
    getDataForResolverFragment: SingularReaderSelector => mixed,
  ): [T /* Answer */, ?DataID /* Seen record */] {
    return [evaluate().resolverResult, undefined];
  }
  invalidateDataIDs(updatedDataIDs: Set<DataID>): void {}
}

function addDependencyEdge(edges, from, to): void {
  let set = edges.get(from);
  if (!set) {
    set = new Set();
    edges.set(from, set);
  }
  set.add(to);
}

class RecordResolverCache implements ResolverCache {
  _resolverIDToRecordIDs: Map<ResolverID, Set<DataID>>;
  _recordIDToResolverIDs: Map<DataID, Set<ResolverID>>;

  _getRecordSource: () => MutableRecordSource;

  constructor(getRecordSource: () => MutableRecordSource) {
    this._resolverIDToRecordIDs = new Map();
    this._recordIDToResolverIDs = new Map();
    this._getRecordSource = getRecordSource;
  }

  readFromCacheOrEvaluate<T>(
    record: Record,
    field: ReaderRelayResolver,
    variables: Variables,
    evaluate: () => EvaluationResult<T>,
    getDataForResolverFragment: SingularReaderSelector => mixed,
  ): [T /* Answer */, ?DataID /* Seen record */] {
    const recordSource = this._getRecordSource();
    const recordID = RelayModernRecord.getDataID(record);

    const storageKey = getStorageKey(field, variables);
    let linkedID = RelayModernRecord.getLinkedRecordID(record, storageKey);
    let linkedRecord = linkedID == null ? null : recordSource.get(linkedID);
    if (
      linkedRecord == null ||
      this._isInvalid(linkedRecord, getDataForResolverFragment)
    ) {
      // Cache miss; evaluate the selector and store the result in a new record:
      linkedID = linkedID ?? generateClientID(recordID, storageKey);
      linkedRecord = RelayModernRecord.create(linkedID, '__RELAY_RESOLVER__');

      const evaluationResult = evaluate();
      RelayModernRecord.setValue(
        linkedRecord,
        RELAY_RESOLVER_VALUE_KEY,
        evaluationResult.resolverResult,
      );
      RelayModernRecord.setValue(
        linkedRecord,
        RELAY_RESOLVER_INPUTS_KEY,
        evaluationResult.fragmentValue,
      );
      RelayModernRecord.setValue(
        linkedRecord,
        RELAY_RESOLVER_READER_SELECTOR_KEY,
        evaluationResult.readerSelector,
      );
      recordSource.set(linkedID, linkedRecord);

      // Link the resolver value record to the resolver field of the record being read:
      const nextRecord = RelayModernRecord.clone(record);
      RelayModernRecord.setLinkedRecordID(nextRecord, storageKey, linkedID);
      recordSource.set(RelayModernRecord.getDataID(nextRecord), nextRecord);

      // Put records observed by the resolver into the dependency graph:
      const resolverID = evaluationResult.resolverID;
      addDependencyEdge(this._resolverIDToRecordIDs, resolverID, linkedID);
      addDependencyEdge(this._recordIDToResolverIDs, recordID, resolverID);
      for (const seenRecordID of evaluationResult.seenRecordIDs) {
        addDependencyEdge(
          this._recordIDToResolverIDs,
          seenRecordID,
          resolverID,
        );
      }
    }

    // $FlowFixMe[incompatible-type] - will always be empty
    const answer: T = linkedRecord[RELAY_RESOLVER_VALUE_KEY];
    return [answer, linkedID];
  }

  invalidateDataIDs(
    updatedDataIDs: Set<DataID>, // Mutated in place
  ): void {
    const recordSource = this._getRecordSource();
    const visited: Set<string> = new Set();
    const recordsToVisit = Array.from(updatedDataIDs);
    while (recordsToVisit.length) {
      const recordID = recordsToVisit.pop();
      updatedDataIDs.add(recordID);
      for (const fragment of this._recordIDToResolverIDs.get(recordID) ??
        emptySet) {
        if (!visited.has(fragment)) {
          for (const anotherRecordID of this._resolverIDToRecordIDs.get(
            fragment,
          ) ?? emptySet) {
            this._markInvalidatedResolverRecord(
              anotherRecordID,
              recordSource,
              updatedDataIDs,
            );
            if (!visited.has(anotherRecordID)) {
              recordsToVisit.push(anotherRecordID);
            }
          }
        }
      }
    }
  }

  _markInvalidatedResolverRecord(
    dataID: DataID,
    recordSource: MutableRecordSource, // Written to
    updatedDataIDs: Set<DataID>, // Mutated in place
  ) {
    const record = recordSource.get(dataID);
    if (!record) {
      warning(
        false,
        'Expected a resolver record with ID %s, but it was missing.',
        dataID,
      );
      return;
    }
    const nextRecord = RelayModernRecord.clone(record);
    RelayModernRecord.setValue(
      nextRecord,
      RELAY_RESOLVER_INVALIDATION_KEY,
      true,
    );
    recordSource.set(dataID, nextRecord);
  }

  _isInvalid(
    record: Record,
    getDataForResolverFragment: SingularReaderSelector => mixed,
  ): boolean {
    if (!RelayModernRecord.getValue(record, RELAY_RESOLVER_INVALIDATION_KEY)) {
      return false;
    }
    const originalInputs = RelayModernRecord.getValue(
      record,
      RELAY_RESOLVER_INPUTS_KEY,
    );
    // $FlowFixMe[incompatible-type] - storing values in records is not typed
    const readerSelector: ?SingularReaderSelector = RelayModernRecord.getValue(
      record,
      RELAY_RESOLVER_READER_SELECTOR_KEY,
    );
    if (originalInputs == null || readerSelector == null) {
      warning(
        false,
        'Expected previous inputs and reader selector on resolver record with ID %s, but they were missing.',
        RelayModernRecord.getDataID(record),
      );
      return true;
    }
    const latestValues = getDataForResolverFragment(readerSelector);
    const recycled = recycleNodesInto(originalInputs, latestValues);
    if (recycled !== originalInputs) {
      return true;
    }
    return false;
  }
}

module.exports = {
  NoopResolverCache,
  RecordResolverCache,
};
<|endoftext|>


<commit_before>import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { reportBug } from 'proton-shared/lib/api/reports';
import { APPS } from 'proton-shared/lib/constants';
import { c } from 'ttag';
import {
    FormModal,
    Href,
    Alert,
    Row,
    Field,
    Input,
    Button,
    useToggle,
    Info,
    TextArea,
    Select,
    Label,
    EmailInput,
    useApiWithoutResult,
    useNotifications,
    useConfig
} from 'react-components';

import AttachScreenshot from './AttachScreenshot';
import { collectInfo, getClient } from '../../helpers/report';

const { PROTONVPN_SETTINGS } = APPS;

const BugModal = ({ onClose, username: Username = '', addresses = [], ...rest }) => {
    const { APP_NAME } = useConfig();
    const mailTitles = [
        { value: 'Login problem', text: c('Bug category').t`Login problem` },
        { value: 'Sign up problem', text: c('Bug category').t`Sign up problem` },
        { value: 'Bridge problem', text: c('Bug category').t`Bridge problem` },
        { value: 'Import / export problem', text: c('Bug category').t`Import / export problem` },
        { value: 'Custom domains problem', text: c('Bug category').t`Custom domains problem` },
        { value: 'Payments problem', text: c('Bug category').t`Payments problem` },
        { value: 'Connection problem', text: c('Bug category').t`Connection problem` },
        { value: 'Slow speed problem', text: c('Bug category').t`Slow speed problem` },
        { value: 'VPN problem', text: c('Bug category').t`VPN problem` },
        { value: 'Feature request', text: c('Bug category').t`Feature request` },
        { value: 'Other', text: c('Bug category').t`Other` }
    ];

    const vpnTitles = [
        { value: 'Login problem', text: c('Bug category').t`Login problem` },
        { value: 'Signup problem', text: c('Bug category').t`Signup problem` },
        { value: 'Payments problem', text: c('Bug category').t`Payments problem` },
        { value: 'Installation problem', text: c('Bug category').t`Installation problem` },
        { value: 'Update problem', text: c('Bug category').t`Update problem` },
        { value: 'Application problem', text: c('Bug category').t`Application problem` },
        { value: 'Connection problem', text: c('Bug category').t`Connection problem` },
        { value: 'Speed problem', text: c('Bug category').t`Speed problem` },
        { value: 'Manual setup problem', text: c('Bug category').t`Manual setup problem` },
        { value: 'Website access problem', text: c('Bug category').t`Website access problem` },
        { value: 'Streaming problem', text: c('Bug category').t`Streaming problem` },
        { value: 'Feature request', text: c('Bug category').t`Feature request` }
    ];

    const titles = APP_NAME === PROTONVPN_SETTINGS ? vpnTitles : mailTitles;
    const criticalEmail = APP_NAME === PROTONVPN_SETTINGS ? 'contact@protonvpn.com' : 'security@protonmail.com';
    const clearCacheLink =
        APP_NAME === PROTONVPN_SETTINGS
            ? 'https://protonvpn.com/support/clear-browser-cache-cookies/'
            : 'https://protonmail.com/support/knowledge-base/how-to-clean-cache-and-cookies/';
    const { CLIENT_ID, APP_VERSION, CLIENT_TYPE } = useConfig();
    const Client = getClient(CLIENT_ID);
    const { createNotification } = useNotifications();
    const [{ Email = '' } = {}] = addresses;
    const options = titles.reduce(
        (acc, { text, value }) => {
            acc.push({
                text,
                value: `[${Client}] Bug [${location.path}] ${value}`
            });
            return acc;
        },
        [{ text: c('Action to select a title for the bug report modal').t`Select`, value: '', disabled: true }]
    );
    const [model, update] = useState({
        ...collectInfo(),
        Client,
        ClientVersion: APP_VERSION,
        ClientType: CLIENT_TYPE,
        Title: options[0].value,
        Description: '',
        Username,
        Email
    });
    const { state: showDetails, toggle: toggleDetails } = useToggle(false);
    const [images, setImages] = useState([]);
    const { request, loading } = useApiWithoutResult(reportBug);
    const link = <Href key="linkClearCache" url={clearCacheLink}>{c('Link').t`clearing your browser cache`}</Href>;
    const handleChange = (key) => ({ target }) => update({ ...model, [key]: target.value });

    const getParameters = () => {
        return images.reduce(
            (acc, { name, blob }) => {
                acc[name] = blob;
                return acc;
            },
            { ...model }
        );
    };

    const handleSubmit = async () => {
        await request(getParameters(), 'form');
        onClose();
        createNotification({ text: c('Success').t`Bug reported` });
    };

    useEffect(() => {
        if (!model.Email && addresses.length) {
            const [{ Email = '' }] = addresses;
            update({ ...model, Email });
        }
    }, [addresses]);

    return (
        <FormModal
            onClose={onClose}
            onSubmit={handleSubmit}
            loading={loading}
            submit={c('Action').t`Submit`}
            title={c('Title').t`Report bug`}
            {...rest}
        >
            <Alert>{c('Info').jt`Refreshing the page or ${link} will automatically resolve most issues.`}</Alert>
            <Alert type="warning">{c('Warning')
                .t`Bug reports are not end-to-end encrypted, please do not send any sensitive information.`}</Alert>
            {Username ? null : (
                <Row>
                    {c('Label').t`Proton username`}
                    <Field>
                        <Input
                            id="Username"
                            value={model.Username}
                            onChange={handleChange('Username')}
                            placeholder={c('Placeholder').t`Proton username`}
                        />
                    </Field>
                </Row>
            )}
            <Row>
                {c('Label').t`Email address`}
                <Field>
                    <EmailInput
                        id="Email"
                        value={model.Email}
                        onChange={handleChange('Email')}
                        placeholder={c('Placeholder').t`Please make sure to give us a way to contact you`}
                        required
                    />
                </Field>
            </Row>
            <Row>
                {c('Label').t`Category`}
                <Field>
                    <Select
                        id="Title"
                        value={model.Title}
                        options={options}
                        onChange={handleChange('Title')}
                        required
                    />
                </Field>
            </Row>
            <Row>
                {c('Label').t`What happened?`}
                <Field>
                    <TextArea
                        id="Description"
                        value={model.Description}
                        onChange={handleChange('Description')}
                        placeholder={c('Placeholder').t`Please describe the problem and include any error messages`}
                        required
                    />
                </Field>
            </Row>
            <Row>

                    {c('Label').t`Attach screenshots`}
                    <Info url="https://protonmail.com/support/knowledge-base/screenshot-reporting-bugs/" />

                <Field>
                    <AttachScreenshot id="Attachments" onUpload={setImages} onReset={() => setImages([])} />
                </Field>
            </Row>
            <Row>
                {c('Label').t`System information`}
                <Button onClick={toggleDetails}>
                    {showDetails ? c('Action').t`Hide info` : c('Action').t`Show info`}
                </Button>
            </Row>
            {showDetails ? (
                <>
                    <Row>
                        {c('Label').t`Operating system`}
                        <Field>
                            <Input
                                id="OS"
                                value={model.OS}
                                onChange={handleChange('OS')}
                                placeholder={c('Placeholder').t`OS name`}
                            />
                        </Field>
                    </Row>
                    <Row>
                        {c('Label').t`Operating system version`}
                        <Field>
                            <Input
                                id="OSVersion"
                                value={model.OSVersion}
                                onChange={handleChange('OSVersion')}
                                placeholder={c('Placeholder').t`OS version`}
                            />
                        </Field>
                    </Row>
                    <Row>
                        {c('Label').t`Browser`}
                        <Field>
                            <Input
                                id="Browser"
                                value={model.Browser}
                                onChange={handleChange('Browser')}
                                placeholder={c('Placeholder').t`Browser name`}
                            />
                        </Field>
                    </Row>
                    <Row>
                        {c('Label').t`Browser version`}
                        <Field>
                            <Input
                                id="BrowserVersion"
                                value={model.BrowserVersion}
                                onChange={handleChange('BrowserVersion')}
                                placeholder={c('Placeholder').t`Browser version`}
                            />
                        </Field>
                    </Row>
                </>
            ) : null}
            <Alert>{c('Info').t`Contact us at ${criticalEmail} for critical security issues.`}</Alert>
        </FormModal>
    );
};

BugModal.propTypes = {
    onClose: PropTypes.func,
    username: PropTypes.string,
    addresses: PropTypes.array
};

export default BugModal;
<commit_msg>Update text to make it shorter<commit_after>import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { reportBug } from 'proton-shared/lib/api/reports';
import { APPS } from 'proton-shared/lib/constants';
import { c } from 'ttag';
import {
    FormModal,
    Href,
    Alert,
    Row,
    Field,
    Input,
    Button,
    useToggle,
    Info,
    TextArea,
    Select,
    Label,
    EmailInput,
    useApiWithoutResult,
    useNotifications,
    useConfig
} from 'react-components';

import AttachScreenshot from './AttachScreenshot';
import { collectInfo, getClient } from '../../helpers/report';

const { PROTONVPN_SETTINGS } = APPS;

const BugModal = ({ onClose, username: Username = '', addresses = [], ...rest }) => {
    const { APP_NAME } = useConfig();
    const mailTitles = [
        { value: 'Login problem', text: c('Bug category').t`Login problem` },
        { value: 'Sign up problem', text: c('Bug category').t`Sign up problem` },
        { value: 'Bridge problem', text: c('Bug category').t`Bridge problem` },
        { value: 'Import / export problem', text: c('Bug category').t`Import / export problem` },
        { value: 'Custom domains problem', text: c('Bug category').t`Custom domains problem` },
        { value: 'Payments problem', text: c('Bug category').t`Payments problem` },
        { value: 'Connection problem', text: c('Bug category').t`Connection problem` },
        { value: 'Slow speed problem', text: c('Bug category').t`Slow speed problem` },
        { value: 'VPN problem', text: c('Bug category').t`VPN problem` },
        { value: 'Feature request', text: c('Bug category').t`Feature request` },
        { value: 'Other', text: c('Bug category').t`Other` }
    ];

    const vpnTitles = [
        { value: 'Login problem', text: c('Bug category').t`Login problem` },
        { value: 'Signup problem', text: c('Bug category').t`Signup problem` },
        { value: 'Payments problem', text: c('Bug category').t`Payments problem` },
        { value: 'Installation problem', text: c('Bug category').t`Installation problem` },
        { value: 'Update problem', text: c('Bug category').t`Update problem` },
        { value: 'Application problem', text: c('Bug category').t`Application problem` },
        { value: 'Connection problem', text: c('Bug category').t`Connection problem` },
        { value: 'Speed problem', text: c('Bug category').t`Speed problem` },
        { value: 'Manual setup problem', text: c('Bug category').t`Manual setup problem` },
        { value: 'Website access problem', text: c('Bug category').t`Website access problem` },
        { value: 'Streaming problem', text: c('Bug category').t`Streaming problem` },
        { value: 'Feature request', text: c('Bug category').t`Feature request` }
    ];

    const titles = APP_NAME === PROTONVPN_SETTINGS ? vpnTitles : mailTitles;
    const criticalEmail = APP_NAME === PROTONVPN_SETTINGS ? 'contact@protonvpn.com' : 'security@protonmail.com';
    const clearCacheLink =
        APP_NAME === PROTONVPN_SETTINGS
            ? 'https://protonvpn.com/support/clear-browser-cache-cookies/'
            : 'https://protonmail.com/support/knowledge-base/how-to-clean-cache-and-cookies/';
    const { CLIENT_ID, APP_VERSION, CLIENT_TYPE } = useConfig();
    const Client = getClient(CLIENT_ID);
    const { createNotification } = useNotifications();
    const [{ Email = '' } = {}] = addresses;
    const options = titles.reduce(
        (acc, { text, value }) => {
            acc.push({
                text,
                value: `[${Client}] Bug [${location.path}] ${value}`
            });
            return acc;
        },
        [{ text: c('Action to select a title for the bug report modal').t`Select`, value: '', disabled: true }]
    );
    const [model, update] = useState({
        ...collectInfo(),
        Client,
        ClientVersion: APP_VERSION,
        ClientType: CLIENT_TYPE,
        Title: options[0].value,
        Description: '',
        Username,
        Email
    });
    const { state: showDetails, toggle: toggleDetails } = useToggle(false);
    const [images, setImages] = useState([]);
    const { request, loading } = useApiWithoutResult(reportBug);
    const link = <Href key="linkClearCache" url={clearCacheLink}>{c('Link').t`clearing your browser cache`}</Href>;
    const handleChange = (key) => ({ target }) => update({ ...model, [key]: target.value });

    const getParameters = () => {
        return images.reduce(
            (acc, { name, blob }) => {
                acc[name] = blob;
                return acc;
            },
            { ...model }
        );
    };

    const handleSubmit = async () => {
        await request(getParameters(), 'form');
        onClose();
        createNotification({ text: c('Success').t`Bug reported` });
    };

    useEffect(() => {
        if (!model.Email && addresses.length) {
            const [{ Email = '' }] = addresses;
            update({ ...model, Email });
        }
    }, [addresses]);

    return (
        <FormModal
            onClose={onClose}
            onSubmit={handleSubmit}
            loading={loading}
            submit={c('Action').t`Submit`}
            title={c('Title').t`Report bug`}
            {...rest}
        >
            <Alert>{c('Info').jt`Refreshing the page or ${link} will automatically resolve most issues.`}</Alert>
            <Alert type="warning">{c('Warning')
                .t`Bug reports are not end-to-end encrypted, please do not send any sensitive information.`}</Alert>
            {Username ? null : (
                <Row>
                    {c('Label').t`Proton username`}
                    <Field>
                        <Input
                            id="Username"
                            value={model.Username}
                            onChange={handleChange('Username')}
                            placeholder={c('Placeholder').t`Proton username`}
                        />
                    </Field>
                </Row>
            )}
            <Row>
                {c('Label').t`Email address`}
                <Field>
                    <EmailInput
                        id="Email"
                        value={model.Email}
                        onChange={handleChange('Email')}
                        placeholder={c('Placeholder').t`A way to contact you`}
                        required
                    />
                </Field>
            </Row>
            <Row>
                {c('Label').t`Category`}
                <Field>
                    <Select
                        id="Title"
                        value={model.Title}
                        options={options}
                        onChange={handleChange('Title')}
                        required
                    />
                </Field>
            </Row>
            <Row>
                {c('Label').t`What happened?`}
                <Field>
                    <TextArea
                        id="Description"
                        value={model.Description}
                        onChange={handleChange('Description')}
                        placeholder={c('Placeholder').t`Please describe the problem and include any error messages`}
                        required
                    />
                </Field>
            </Row>
            <Row>

                    {c('Label').t`Attach screenshots`}
                    <Info url="https://protonmail.com/support/knowledge-base/screenshot-reporting-bugs/" />

                <Field>
                    <AttachScreenshot id="Attachments" onUpload={setImages} onReset={() => setImages([])} />
                </Field>
            </Row>
            <Row>
                {c('Label').t`System information`}
                <Button onClick={toggleDetails}>
                    {showDetails ? c('Action').t`Hide info` : c('Action').t`Show info`}
                </Button>
            </Row>
            {showDetails ? (
                <>
                    <Row>
                        {c('Label').t`Operating system`}
                        <Field>
                            <Input
                                id="OS"
                                value={model.OS}
                                onChange={handleChange('OS')}
                                placeholder={c('Placeholder').t`OS name`}
                            />
                        </Field>
                    </Row>
                    <Row>
                        {c('Label').t`Operating system version`}
                        <Field>
                            <Input
                                id="OSVersion"
                                value={model.OSVersion}
                                onChange={handleChange('OSVersion')}
                                placeholder={c('Placeholder').t`OS version`}
                            />
                        </Field>
                    </Row>
                    <Row>
                        {c('Label').t`Browser`}
                        <Field>
                            <Input
                                id="Browser"
                                value={model.Browser}
                                onChange={handleChange('Browser')}
                                placeholder={c('Placeholder').t`Browser name`}
                            />
                        </Field>
                    </Row>
                    <Row>
                        {c('Label').t`Browser version`}
                        <Field>
                            <Input
                                id="BrowserVersion"
                                value={model.BrowserVersion}
                                onChange={handleChange('BrowserVersion')}
                                placeholder={c('Placeholder').t`Browser version`}
                            />
                        </Field>
                    </Row>
                </>
            ) : null}
            <Alert>{c('Info').t`Contact us at ${criticalEmail} for critical security issues.`}</Alert>
        </FormModal>
    );
};

BugModal.propTypes = {
    onClose: PropTypes.func,
    username: PropTypes.string,
    addresses: PropTypes.array
};

export default BugModal;
<|endoftext|>


<commit_before>'use strict';

/**
 * Boom hook
 */

// Public node modules.
const _ = require('lodash');
const Boom = require('boom');
const delegate = require('delegates');

module.exports = strapi => {
  return {
    /**
     * Initialize the hook
     */

    initialize: function(cb) {
      this.delegator = delegate(strapi.app.context, 'response');
      this.createResponses();

      strapi.app.use(async (ctx, next) => {
        try {
          // App logic.
          await next();
        } catch (error) {
          // Log error.
          strapi.log.error(error);

          // Wrap error into a Boom's response.
          ctx.status = error.status || 500;
          ctx.body = _.get(ctx.body, 'isBoom')
            ? ctx.body || error && error.message
            : Boom.wrap(error, ctx.status, ctx.body || error.message);
        }

        if (ctx.response.headers.location) {
          return;
        }

        // Empty body is considered as `notFound` response.
        if (!ctx.body) {
          ctx.notFound();
        }

        if (ctx.body.isBoom && ctx.body.data) {
          ctx.body.output.payload.message = ctx.body.data;
        }

        // Format `ctx.body` and `ctx.status`.
        ctx.status = ctx.body.isBoom ? ctx.body.output.statusCode : ctx.status;
        ctx.body = ctx.body.isBoom ? ctx.body.output.payload : ctx.body;
      });

      cb();
    },

    // Custom function to avoid ctx.body repeat
    createResponses: function() {
      Object.keys(Boom).forEach(key => {
        strapi.app.response[key] = function(...rest) {
          this.body = Boom[key](...rest);
        };

        this.delegator.method(key);
      });

      strapi.app.response.send = function(data) {
        this.status = 200;
        this.body = data;
      };

      strapi.app.response.created = function(data) {
        this.status = 201;
        this.body = data;
      };

      this.delegator
        .method('send')
        .method('created');
    }
  };
};
<commit_msg>Set ctx.status when Boom method is called<commit_after>'use strict';

/**
 * Boom hook
 */

// Public node modules.
const _ = require('lodash');
const Boom = require('boom');
const delegate = require('delegates');

module.exports = strapi => {
  return {
    /**
     * Initialize the hook
     */

    initialize: function(cb) {
      this.delegator = delegate(strapi.app.context, 'response');
      this.createResponses();

      strapi.app.use(async (ctx, next) => {
        try {
          // App logic.
          await next();
        } catch (error) {
          // Log error.
          strapi.log.error(error);

          // Wrap error into a Boom's response.
          ctx.status = error.status || 500;
          ctx.body = _.get(ctx.body, 'isBoom')
            ? ctx.body || error && error.message
            : Boom.wrap(error, ctx.status, ctx.body || error.message);
        }

        if (ctx.response.headers.location) {
          return;
        }

        // Empty body is considered as `notFound` response.
        if (!ctx.body) {
          ctx.notFound();
        }

        if (ctx.body.isBoom && ctx.body.data) {
          ctx.body.output.payload.message = ctx.body.data;
        }

        // Format `ctx.body` and `ctx.status`.
        ctx.status = ctx.body.isBoom ? ctx.body.output.statusCode : ctx.status;
        ctx.body = ctx.body.isBoom ? ctx.body.output.payload : ctx.body;
      });

      cb();
    },

    // Custom function to avoid ctx.body repeat
    createResponses: function() {
      Object.keys(Boom).forEach(key => {
        strapi.app.response[key] = function(...rest) {
          const error = Boom[key](...rest);

          this.status = error.isBoom ? error.output.statusCode : this.status;
          this.body = Boom[key](...rest);
        };

        this.delegator.method(key);
      });

      strapi.app.response.send = function(data) {
        this.status = 200;
        this.body = data;
      };

      strapi.app.response.created = function(data) {
        this.status = 201;
        this.body = data;
      };

      this.delegator
        .method('send')
        .method('created');
    }
  };
};
<|endoftext|>


<commit_before>const idea = (state = [], action) => {
  switch (action.type) {
    case "SET_IDEAS":
      return action.ideas
    case "ADD_IDEA":
      return [...state, action.idea]
    case "UPDATE_IDEA" :
      return state.map(idea => {
        return (idea.id === action.ideaId) ? Object.assign({}, idea, action.newAttributes) : idea
      })
    case "DELETE_IDEA" :
      return state.filter(idea => {
        return idea.id !== action.ideaId
      })
    default:
      return state
  }
}

export default idea
<commit_msg>Refactor to avoid using curly-brace-multi-line filter<commit_after>const idea = (state = [], action) => {
  switch (action.type) {
    case "SET_IDEAS":
      return action.ideas
    case "ADD_IDEA":
      return [...state, action.idea]
    case "UPDATE_IDEA" :
      return state.map(idea => {
        return (idea.id === action.ideaId) ? Object.assign({}, idea, action.newAttributes) : idea
      })
    case "DELETE_IDEA" :
      return state.filter(idea => idea.id !== action.ideaId)
    default:
      return state
  }
}

export default idea
<|endoftext|>


<commit_before>var _fs = require('fs');
var _nodeMcuConnector = require('./NodeMcuConnector');
var _serialTerminal = require('./SerialTerminal');
var _path = require('path');
var _loggingFacility = require('logging-facility');

// NodeMCU-Tool Context Logger
var _logger = _loggingFacility.getLogger('NodeMCU-Tool');

// NodeMCU Context Logger
var _mculogger = _loggingFacility.getLogger('NodeMCU');

// Serial Terminal Context Logger
var _terminallogger = _loggingFacility.getLogger('SerialTerminal');

// output
var outputHandler = function(message){
    console.log(message);
};

var writeOutput = function(message){
    if (outputHandler){
        outputHandler(message);
    }
};

// global options
var _options = {
    // serial port baudrate
    baudrate: 115200,

    // serial device connected to nodemcu
    device: '/dev/ttyUSB0',

    // delay after opening the connection
    connectionDelay: 0
};

// Programmatic Access to the core functions
var Tool = {

    // access the connector directly
    Connector: _nodeMcuConnector,

    // set output handler
    onOutput: function (handler) {
        outputHandler = handler;
    },

    // set connector options
    setOptions: function(opt){
        // merge with default options
        Object.keys(_options).forEach(function(key){
            _options[key] = opt[key] || _options[key];
        });
    }
};

// helper function to create a NodeMCU Tool Connection
var getConnection = function(cb){

    // create new connector
    var connector = new _nodeMcuConnector(_options.device, _options.baudrate);

    // open connection with connection check
    connector.connect(function(error, response){
        if (error) {
            _logger.error('Unable to establish connection - ' + error);

            // finished!
            connector.disconnect();
        }else{
            // status message
            _logger.log('Connected');
            _mculogger.log(response);

            cb(connector);
        }
    }, true, _options.connectionDelay);
};

// show file-system info
Tool.fsinfo = function(format){

    // try to establish a connection to the module
    getConnection(function(connector){

        connector.fsinfo(function(err, meta, files){

            // finished!
            connector.disconnect();

            if (err){
                _logger.error(err);
            }else{

                // json output - third party applications
                if (format == 'json') {
                    writeOutput(JSON.stringify({
                        files: files,
                        meta: meta
                    }));

                // raw format - suitable for use in bash scripts
                }else if (format == 'raw'){
                    // print fileinfo
                    files.forEach(function(file){
                        writeOutput(file.name);
                    });

                }else{
                    _mculogger.log('Free Disk Space: ' + meta.remaining + ' KB | Total: ' + meta.total + ' KB | ' + files.length + ' Files');

                    // files found ?
                    if (files.length==0){
                        _mculogger.log('No Files found - have you created the file-system?');
                    }else{
                        _mculogger.log('Files stored into Flash (SPIFFS)');

                        // print fileinfo
                        files.forEach(function(file){
                            writeOutput('\t  |- ' + file.name + ' (' + file.size + ' Bytes)');
                        });
                    }
                }
            }
        });
    });
};

// upload a local file to nodemcu
Tool.upload = function(localFiles, options, onProgess){

    // the index of the current uploaded file
    var fileUploadIndex = 0;

    var uploadFile = function(connector, localFile, remoteFilename, onComplete){

        // increment upload index
        fileUploadIndex++;

        // get file stats
        try{
            var fileInfo = _fs.statSync(localFile);

        // local file available
        }catch (err){
            _logger.error('Local file not found "' + localFile + '" skipping...');
            onComplete();
            return;
        }

        // display filename
        _logger.log('Uploading "' + localFile + '" >> "' + remoteFilename + '"...');

        // trigger a progress update
        onProgess(0, fileInfo.size, fileUploadIndex);

        // normalize the remote filename (strip relative parts)
        remoteFilename = remoteFilename.replace(/\.\.\//g, '').replace(/\.\./g, '').replace(/^\.\//, '');

        // delete old file (may existent)
        connector.removeFile(remoteFilename, function(err){

            // handle error
            if (err){
                connector.disconnect();
                _logger.error(err);
                return;
            }

            // start the file transfer
            connector.upload(localFile, remoteFilename, options,

                // onComplete
                function(err){

                    // handle error
                    if (err){
                        connector.disconnect();
                        _logger.error(err);
                        return;
                    }

                    // compile flag set ? and is a lua file ?
                    if (options.compile && _path.extname(localFile).toLowerCase() == '.lua'){
                        _mculogger.log(' |- compiling lua file..');

                        connector.compile(remoteFilename, function(error){
                            // success ? empty line will return (null)
                            if (error){
                                connector.disconnect();
                                _mculogger.error('Error: ' + error);
                            }else{
                                _mculogger.log(' |- success');

                                // drop original lua file
                                connector.removeFile(remoteFilename, function(error){

                                    if (error){
                                        connector.disconnect();
                                        _mculogger.error('Error: ' + error);
                                        return;
                                    }

                                    _mculogger.log(' |- original Lua file removed');
                                    onComplete();
                                });
                            }
                        });
                    }else{
                        // directly call complete handler
                        onComplete();
                    }
                },

                // on progress handler
                function(current, total){
                    // proxy and append file-number
                    onProgess(current, total, fileUploadIndex);
                }
            );
        });
    };

    // try to establish a connection to the module
    getConnection(function(connector){

        // single file upload ?
        if (localFiles.length == 1){
            // extract first element
            var localFile = localFiles[0];

            // filename defaults to original filename minus path.
            // this behaviour can be overridden by --keeppath and --remotename options
            var remoteFile = options.remotename ? options.remotename : (options.keeppath ? localFile : _path.basename(localFile));

            // start single file upload
            uploadFile(connector, localFile, remoteFile, function(){
                // close connection
                connector.disconnect();

                // log message
                _logger.log('File Transfer complete!');
            });

        // bulk upload ?
        }else{

            var uploadNext = function(){

                // file available ?
                if (localFiles.length > 0){

                    // extract file
                    var localFile = localFiles.shift();

                    // keep-path option set ?
                    var remoteFile = (options.keeppath ? localFile : _path.basename(localFile));

                    // trigger upload
                    uploadFile(connector, localFile, remoteFile, uploadNext);

                // no more file available
                }else{
                    // close connection
                    connector.disconnect();

                    // log message
                    _logger.log('Bulk File Transfer complete!');
                }
            };

            // trigger initial upload
            uploadNext();
        }
    });
};

// download a remote file from nodemcu
Tool.download = function(remoteFile){
    // strip path
    var localFilename = _path.basename(remoteFile);

    // local file with same name already available ?
    if (_fs.existsSync(remoteFile)){
        // change filename
        localFilename += '.' + (new Date().getTime());

        _logger.log('Local file "' + remoteFile + '" already exist - new file renamed to "' + localFilename + '"');
    }

    // try to establish a connection to the module
    getConnection(function(connector){
        _logger.log('Downloading "' + remoteFile + '" ...');

        connector.download(remoteFile,
            // onComplete
            function(err, filedata){
                // finished!
                connector.disconnect();

                if (err){
                    _logger.error('Data Transfer FAILED!');
                }else{
                    _logger.log('Data Transfer complete!');

                    // store local file
                    _fs.writeFileSync(localFilename, filedata);

                    _logger.log('File "' + localFilename + '" created');
                }
            }
        );
    });
};

// run a file on NodeMCU (.lc or .lua)
Tool.run = function(filename){

    // try to establish a connection to the module
    getConnection(function(connector){
        connector.run(filename, function(err, output){
            // finished!
            connector.disconnect();

            if (err){
                _mculogger.error(err);
            }else{
                // show command response
                _mculogger.log('Running "' + filename + '"');
                _mculogger.log('>----------------------------->');
                writeOutput(output);
                _mculogger.log('>----------------------------->');
            }
        });
    });
};

// removes a file from NodeMCU
Tool.remove = function(filename){

    // try to establish a connection to the module
    getConnection(function(connector){
        connector.removeFile(filename, function(err){
            // finished!
            connector.disconnect();

            if (err){
                _mculogger.error(err);
            }else{
                // just show complete message (no feedback from nodemcu)
                _mculogger.log('File "' + filename + '" removed!');
            }
        });
    });
};

// format the file system
Tool.mkfs = function(){

    // try to establish a connection to the module
    getConnection(function(connector){

        _mculogger.log('Formatting the file system...this will take around ~30s');

        connector.format(function(err, response){
            // finished!
            connector.disconnect();

            if (err){
                _mculogger.error('Formatting failed - ' + err);
            }else{
                // just show complete message
                _mculogger.log('File System created | ' + response);
            }
        });
    });
};

// serial terminal <> console session
Tool.terminal = function(initialCommand){
    // create new connector
    var terminal = new _serialTerminal();

    _terminallogger.log('Starting Terminal Mode - press ctrl+c to exit');

    // run initial command before starting terminal session ?
    if (initialCommand){
        terminal.onConnect(function(device){
            device.write(initialCommand + '\n');
        });
    }

    // start
    terminal.passthrough(_options.device, _options.baudrate, function(err){
        if (err){
            _terminallogger.error(err);
        }else{
            _terminallogger.log('Connection closed');
        }
    });
};

// show serial devices connected to the system
Tool.devices = function(showAll, jsonOutput){
    // create new connector
    var connector = new _nodeMcuConnector(_options.device, _options.baudrate);

    // retrieve the device list (not bound to an opened connection)
    connector.deviceInfo(showAll, function(err, devices){
        if (err){
            _mculogger.error('Cannot retrieve serial device list - ' + err);
        }else{

            if (jsonOutput){
                writeOutput(JSON.stringify(devices));
            }else{
                // just show complete message
                if (devices.length == 0){
                    _mculogger.error('No Connected Devices found | Total: ' + devices.length);
                }else{
                    _mculogger.log('Connected Devices | Total: ' + devices.length);

                    // print fileinfo
                    devices.forEach(function(device){
                        writeOutput('\t  |- ' + device.comName + ' (' + device.manufacturer + ', ' + device.pnpId + ')');
                    });
                }
            }
        }
    });
};

// Reset of the NodeMCU Module
Tool.reset = function(){

    // create new connector
    var connector = new _nodeMcuConnector(_options.device, _options.baudrate);

    // open connection without connection check
    connector.connect(function(error, response){
        if (error) {
            _logger.error('Unable to establish connection - ' + error);
        }else{
            // status message
            _logger.log('Connected');

            // execute reset
            connector.reset(function(err){
                // finished!
                connector.disconnect();

                if (err){
                    _mculogger.error(err);
                }else{
                    _mculogger.log('Hard-Reset executed (100ms)');
                }
            })
        }
    }, false);
};

// Reset of the NodeMCU Module
Tool.softreset = function(){

    // try to establish a connection to the module
    getConnection(function(connector){

        connector.softreset(function(err){
            // finished!
            connector.disconnect();

            if (err){
                _mculogger.error(err);
            }else{
                _mculogger.log('Soft-Reset executed (node.restart())');
            }
        });

    });
};

module.exports = Tool;
<commit_msg>Fix crashing when trying to upload a folder<commit_after>var _fs = require('fs');
var _nodeMcuConnector = require('./NodeMcuConnector');
var _serialTerminal = require('./SerialTerminal');
var _path = require('path');
var _loggingFacility = require('logging-facility');

// NodeMCU-Tool Context Logger
var _logger = _loggingFacility.getLogger('NodeMCU-Tool');

// NodeMCU Context Logger
var _mculogger = _loggingFacility.getLogger('NodeMCU');

// Serial Terminal Context Logger
var _terminallogger = _loggingFacility.getLogger('SerialTerminal');

// output
var outputHandler = function(message){
    console.log(message);
};

var writeOutput = function(message){
    if (outputHandler){
        outputHandler(message);
    }
};

// global options
var _options = {
    // serial port baudrate
    baudrate: 115200,

    // serial device connected to nodemcu
    device: '/dev/ttyUSB0',

    // delay after opening the connection
    connectionDelay: 0
};

// Programmatic Access to the core functions
var Tool = {

    // access the connector directly
    Connector: _nodeMcuConnector,

    // set output handler
    onOutput: function (handler) {
        outputHandler = handler;
    },

    // set connector options
    setOptions: function(opt){
        // merge with default options
        Object.keys(_options).forEach(function(key){
            _options[key] = opt[key] || _options[key];
        });
    }
};

// helper function to create a NodeMCU Tool Connection
var getConnection = function(cb){

    // create new connector
    var connector = new _nodeMcuConnector(_options.device, _options.baudrate);

    // open connection with connection check
    connector.connect(function(error, response){
        if (error) {
            _logger.error('Unable to establish connection - ' + error);

            // finished!
            connector.disconnect();
        }else{
            // status message
            _logger.log('Connected');
            _mculogger.log(response);

            cb(connector);
        }
    }, true, _options.connectionDelay);
};

// show file-system info
Tool.fsinfo = function(format){

    // try to establish a connection to the module
    getConnection(function(connector){

        connector.fsinfo(function(err, meta, files){

            // finished!
            connector.disconnect();

            if (err){
                _logger.error(err);
            }else{

                // json output - third party applications
                if (format == 'json') {
                    writeOutput(JSON.stringify({
                        files: files,
                        meta: meta
                    }));

                // raw format - suitable for use in bash scripts
                }else if (format == 'raw'){
                    // print fileinfo
                    files.forEach(function(file){
                        writeOutput(file.name);
                    });

                }else{
                    _mculogger.log('Free Disk Space: ' + meta.remaining + ' KB | Total: ' + meta.total + ' KB | ' + files.length + ' Files');

                    // files found ?
                    if (files.length==0){
                        _mculogger.log('No Files found - have you created the file-system?');
                    }else{
                        _mculogger.log('Files stored into Flash (SPIFFS)');

                        // print fileinfo
                        files.forEach(function(file){
                            writeOutput('\t  |- ' + file.name + ' (' + file.size + ' Bytes)');
                        });
                    }
                }
            }
        });
    });
};

// upload a local file to nodemcu
Tool.upload = function(localFiles, options, onProgess){

    // the index of the current uploaded file
    var fileUploadIndex = 0;

    var uploadFile = function(connector, localFile, remoteFilename, onComplete){

        // increment upload index
        fileUploadIndex++;

        // get file stats
        try{
            var fileInfo = _fs.statSync(localFile);
        // local file available
        } catch (err){
            _logger.error('Local file not found "' + localFile + '" skipping...');
            onComplete();
            return;
        }

        // check if file is directory
        if (fileInfo.isDirectory()) {
            _mculogger.error('Path "' + localFile + '" is a directory.');
            onComplete(1);
            return;
        }

        // display filename
        _logger.log('Uploading "' + localFile + '" >> "' + remoteFilename + '"...');

        // trigger a progress update
        onProgess(0, fileInfo.size, fileUploadIndex);

        // normalize the remote filename (strip relative parts)
        remoteFilename = remoteFilename.replace(/\.\.\//g, '').replace(/\.\./g, '').replace(/^\.\//, '');

        // delete old file (may existent)
        connector.removeFile(remoteFilename, function(err){

            // handle error
            if (err){
                connector.disconnect();
                _logger.error(err);
                return;
            }

            // start the file transfer
            connector.upload(localFile, remoteFilename, options,

                // onComplete
                function(err){

                    // handle error
                    if (err){
                        connector.disconnect();
                        _logger.error(err);
                        return;
                    }

                    // compile flag set ? and is a lua file ?
                    if (options.compile && _path.extname(localFile).toLowerCase() == '.lua'){
                        _mculogger.log(' |- compiling lua file..');

                        connector.compile(remoteFilename, function(error){
                            // success ? empty line will return (null)
                            if (error){
                                connector.disconnect();
                                _mculogger.error('Error: ' + error);
                            }else{
                                _mculogger.log(' |- success');

                                // drop original lua file
                                connector.removeFile(remoteFilename, function(error){

                                    if (error){
                                        connector.disconnect();
                                        _mculogger.error('Error: ' + error);
                                        return;
                                    }

                                    _mculogger.log(' |- original Lua file removed');
                                    onComplete();
                                });
                            }
                        });
                    }else{
                        // directly call complete handler
                        onComplete();
                    }
                },

                // on progress handler
                function(current, total){
                    // proxy and append file-number
                    onProgess(current, total, fileUploadIndex);
                }
            );
        });
    };

    // try to establish a connection to the module
    getConnection(function(connector){

        // single file upload ?
        if (localFiles.length == 1){
            // extract first element
            var localFile = localFiles[0];

            // filename defaults to original filename minus path.
            // this behaviour can be overridden by --keeppath and --remotename options
            var remoteFile = options.remotename ? options.remotename : (options.keeppath ? localFile : _path.basename(localFile));

            // start single file upload
            uploadFile(connector, localFile, remoteFile, function(err){
                // close connection
                connector.disconnect();

                // log message
                if (!err) _logger.log('File Transfer complete!');
            });

        // bulk upload ?
        }else{

            var uploadNext = function(){

                // file available ?
                if (localFiles.length > 0){

                    // extract file
                    var localFile = localFiles.shift();

                    // keep-path option set ?
                    var remoteFile = (options.keeppath ? localFile : _path.basename(localFile));

                    // trigger upload
                    uploadFile(connector, localFile, remoteFile, uploadNext);

                // no more file available
                }else{
                    // close connection
                    connector.disconnect();

                    // log message
                    _logger.log('Bulk File Transfer complete!');
                }
            };

            // trigger initial upload
            uploadNext();
        }
    });
};

// download a remote file from nodemcu
Tool.download = function(remoteFile){
    // strip path
    var localFilename = _path.basename(remoteFile);

    // local file with same name already available ?
    if (_fs.existsSync(remoteFile)){
        // change filename
        localFilename += '.' + (new Date().getTime());

        _logger.log('Local file "' + remoteFile + '" already exist - new file renamed to "' + localFilename + '"');
    }

    // try to establish a connection to the module
    getConnection(function(connector){
        _logger.log('Downloading "' + remoteFile + '" ...');

        connector.download(remoteFile,
            // onComplete
            function(err, filedata){
                // finished!
                connector.disconnect();

                if (err){
                    _logger.error('Data Transfer FAILED!');
                }else{
                    _logger.log('Data Transfer complete!');

                    // store local file
                    _fs.writeFileSync(localFilename, filedata);

                    _logger.log('File "' + localFilename + '" created');
                }
            }
        );
    });
};

// run a file on NodeMCU (.lc or .lua)
Tool.run = function(filename){

    // try to establish a connection to the module
    getConnection(function(connector){
        connector.run(filename, function(err, output){
            // finished!
            connector.disconnect();

            if (err){
                _mculogger.error(err);
            }else{
                // show command response
                _mculogger.log('Running "' + filename + '"');
                _mculogger.log('>----------------------------->');
                writeOutput(output);
                _mculogger.log('>----------------------------->');
            }
        });
    });
};

// removes a file from NodeMCU
Tool.remove = function(filename){

    // try to establish a connection to the module
    getConnection(function(connector){
        connector.removeFile(filename, function(err){
            // finished!
            connector.disconnect();

            if (err){
                _mculogger.error(err);
            }else{
                // just show complete message (no feedback from nodemcu)
                _mculogger.log('File "' + filename + '" removed!');
            }
        });
    });
};

// format the file system
Tool.mkfs = function(){

    // try to establish a connection to the module
    getConnection(function(connector){

        _mculogger.log('Formatting the file system...this will take around ~30s');

        connector.format(function(err, response){
            // finished!
            connector.disconnect();

            if (err){
                _mculogger.error('Formatting failed - ' + err);
            }else{
                // just show complete message
                _mculogger.log('File System created | ' + response);
            }
        });
    });
};

// serial terminal <> console session
Tool.terminal = function(initialCommand){
    // create new connector
    var terminal = new _serialTerminal();

    _terminallogger.log('Starting Terminal Mode - press ctrl+c to exit');

    // run initial command before starting terminal session ?
    if (initialCommand){
        terminal.onConnect(function(device){
            device.write(initialCommand + '\n');
        });
    }

    // start
    terminal.passthrough(_options.device, _options.baudrate, function(err){
        if (err){
            _terminallogger.error(err);
        }else{
            _terminallogger.log('Connection closed');
        }
    });
};

// show serial devices connected to the system
Tool.devices = function(showAll, jsonOutput){
    // create new connector
    var connector = new _nodeMcuConnector(_options.device, _options.baudrate);

    // retrieve the device list (not bound to an opened connection)
    connector.deviceInfo(showAll, function(err, devices){
        if (err){
            _mculogger.error('Cannot retrieve serial device list - ' + err);
        }else{

            if (jsonOutput){
                writeOutput(JSON.stringify(devices));
            }else{
                // just show complete message
                if (devices.length == 0){
                    _mculogger.error('No Connected Devices found | Total: ' + devices.length);
                }else{
                    _mculogger.log('Connected Devices | Total: ' + devices.length);

                    // print fileinfo
                    devices.forEach(function(device){
                        writeOutput('\t  |- ' + device.comName + ' (' + device.manufacturer + ', ' + device.pnpId + ')');
                    });
                }
            }
        }
    });
};

// Reset of the NodeMCU Module
Tool.reset = function(){

    // create new connector
    var connector = new _nodeMcuConnector(_options.device, _options.baudrate);

    // open connection without connection check
    connector.connect(function(error, response){
        if (error) {
            _logger.error('Unable to establish connection - ' + error);
        }else{
            // status message
            _logger.log('Connected');

            // execute reset
            connector.reset(function(err){
                // finished!
                connector.disconnect();

                if (err){
                    _mculogger.error(err);
                }else{
                    _mculogger.log('Hard-Reset executed (100ms)');
                }
            })
        }
    }, false);
};

// Reset of the NodeMCU Module
Tool.softreset = function(){

    // try to establish a connection to the module
    getConnection(function(connector){

        connector.softreset(function(err){
            // finished!
            connector.disconnect();

            if (err){
                _mculogger.error(err);
            }else{
                _mculogger.log('Soft-Reset executed (node.restart())');
            }
        });

    });
};

module.exports = Tool;
<|endoftext|>


<commit_before>/*
 * Service to request and cache a comment thread
 *
 * @author Markus Riegel <riegel.markus@googlemail.com>
 */

angular.module('lpCommentService',[
	'socket',
	'lpConfig'
])

.factory('LpCommentService',[
'Socket','LpConfig',
function(Socket,LpConfig){

	return {

	};

}]);
<commit_msg>first classes<commit_after>/*
 * Service to request and cache a comment thread
 *
 * @author Markus Riegel <riegel.markus@googlemail.com>
 */

angular.module('lpCommentService',[
	'socket',
	'lpConfig'
])

.factory('LpCommentService',[
'Socket','LpConfig',
function(Socket,LpConfig){

	var comments = [],
		loaded = false,
		socketManager = Socket.generateManager(null);

	var loadComments = function(venueId){

	};

	var clearComments = function(){

	};

	return {

	};

}]);
<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var Module = require("./Module");
var NormalModuleMixin = require("webpack-core/lib/NormalModuleMixin");
var SourceMapSource = require("webpack-core/lib/SourceMapSource");
var OriginalSource = require("webpack-core/lib/OriginalSource");
var RawSource = require("webpack-core/lib/RawSource");
var ReplaceSource = require("webpack-core/lib/ReplaceSource");
var ModuleParseError = require("./ModuleParseError");
var TemplateArgumentDependency = require("./dependencies/TemplateArgumentDependency");
var path = require("path");

function NormalModule(request, userRequest, rawRequest, loaders, resource, parser) {
	Module.call(this);
	this.request = request;
	this.userRequest = userRequest;
	this.rawRequest = rawRequest;
	this.parser = parser;
	NormalModuleMixin.call(this, loaders, resource);
	this.meta = {};
	this.assets = {};
	this.built = false;
}
module.exports = NormalModule;

NormalModule.prototype = Object.create(Module.prototype);
NormalModuleMixin.mixin(NormalModule.prototype);

NormalModule.prototype.identifier = function() {
	return this.request;
};

NormalModule.prototype.readableIdentifier = function(requestShortener) {
	return requestShortener.shorten(this.userRequest);
};

NormalModule.prototype.fillLoaderContext = function fillLoaderContext(loaderContext, options, compilation) {
	loaderContext.webpack = true;
	compilation.applyPlugins("normal-module-loader", loaderContext);
	loaderContext.emitFile = function(name, content, sourceMap) {
		if(typeof sourceMap === "string") {
			this.assets[name] = new OriginalSource(content, sourceMap);
		} else if(sourceMap) {
			this.assets[name] = new SourceMapSource(content, name, sourceMap);
		} else {
			this.assets[name] = new RawSource(content);
		}
	}.bind(this);
	loaderContext._compilation = compilation;
	loaderContext._compiler = compilation.compiler;
};

NormalModule.prototype.disconnect = function disconnect() {
	this.built = false;
	Module.prototype.disconnect.call(this);
};

NormalModule.prototype.build = function build(options, compilation, resolver, fs, callback) {
	this.buildTimestamp = new Date().getTime();
	this.built = true;
	return this.doBuild(options, compilation, resolver, fs, function(err) {
		if(err) return callback(err);
		try {
			this.parser.parse(this._source.source(), {
				current: this,
				module: this,
				compilation: compilation,
				options: options
			});
		} catch(e) {
			var source = this._source.source();
			this._source = null;
			return callback(new ModuleParseError(this, source, e));
		}
		return callback();
	}.bind(this));
};

NormalModule.prototype.source = function(dependencyTemplates, outputOptions, requestShortener) {
	var _source = this._source;
	if(!_source) return new RawSource("throw new Error('No source availible');");
	var source = new ReplaceSource(_source);
	function doDep(dep) {
		var template = dependencyTemplates.get(dep.Class);
		if(!template) throw new Error("No template for dependency: " + dep.Class.name);
		template.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
	}
	function doVariable(vars, variable) {
		var name = variable.name;
		var expr = variable.expressionSource(dependencyTemplates, outputOptions, requestShortener);
		vars.push({name: name, expression: expr});
	}
	function doBlock(block) {
		block.dependencies.forEach(doDep);
		block.blocks.forEach(doBlock);
		if(block.variables.length > 0) {
			var vars = [];
			block.variables.forEach(doVariable.bind(null, vars));
			var varNames = [];
			var varExpressions = [];
			var varStartCode = "";
			var varEndCode = "";
			function emitFunction() {
				if(varNames.length == 0) return;

				varStartCode += "/* WEBPACK VAR INJECTION */(function(require, " + varNames.join(", ") + ") {";
				varEndCode = "}.call(exports, require, " + varExpressions.map(function(e) {return e.source()}).join(", ") + "))" + varEndCode;

				varNames.length = 0;
				varExpressions.length = 0;
			}
			vars.forEach(function(v) {
				if(varNames.indexOf(v.name) >= 0) emitFunction();
				varNames.push(v.name);
				varExpressions.push(v.expression);
			});
			emitFunction();
			var start = block.range ? block.range[0] : 0;
			var end = block.range ? block.range[1] : _source.size();
			if(varStartCode) source.insert(start, varStartCode);
			if(varEndCode) source.insert(end, "\n/* WEBPACK VAR INJECTION */" + varEndCode);
		}
	}
	doBlock(this);
	return source;
};

NormalModule.prototype.needRebuild = function needRebuild(fileTimestamps, contextTimestamps) {
	var timestamp = 0;
	this.fileDependencies.forEach(function(file) {
		var ts = fileTimestamps[file];
		if(!ts) timestamp = Infinity;
		if(ts > timestamp) timestamp = ts;
	});
	this.contextDependencies.forEach(function(context) {
		var ts = contextTimestamps[context];
		if(!ts) timestamp = Infinity;
		if(ts > timestamp) timestamp = ts;
	});
	return timestamp >= this.buildTimestamp;
};

NormalModule.prototype.size = function() {
	return this._source ? this._source.size() : -1;
};

NormalModule.prototype.updateHash = function(hash) {
	if(this._source) {
		hash.update("source");
		this._source.updateHash(hash);
	} else
		hash.update("null");
	Module.prototype.updateHash.call(this, hash);
};

NormalModule.prototype.getSourceHash = function() {
	if(!this._source) return "";
	var hash = require("crypto").createHash("md5");
	hash.update(this._source.source());
	return hash.digest("hex");
};

NormalModule.prototype.getAllModuleDependencies = function() {
	var list = [];
	function doDep(dep) {
		if(dep.module && list.indexOf(dep.module) < 0)
			list.push(dep.module);
	}
	function doVariable(variable) {
		variable.dependencies.forEach(doDep);
	}
	function doBlock(block) {
		block.variables.forEach(doVariable);
		block.dependencies.forEach(doDep);
		block.blocks.forEach(doBlock);
	}
	doBlock(this);
	return list;
};

NormalModule.prototype.createTemplate = function(keepModules) {
	var template = new NormalModule("", "", "", [], "", null);
	template._source = this._source;
	template.built = this.built;
	template.templateModules = keepModules;
	var args = template.arguments = [];
	function doDeps(deps) {
		return deps.map(function(dep) {
			if(keepModules.indexOf(dep.module) < 0) {
				var argName = "__webpack_module_template_argument_" + args.length + "__";
				args.push(argName);
				return new TemplateArgumentDependency(argName, dep);
			} else {
				return dep;
			}
		});
	}
	function doVariable(variable, newVariable) {
		variable.dependencies.forEach(doDep);
	}
	function doBlock(block, newBlock) {
		block.variables.forEach(function(variable) {
			var newDependencies = doDeps(variable.dependencies);
			newBlock.addVariable(variable.name, variable.expression, newDependencies);
		});
		newBlock.dependencies = doDeps(block.dependencies);
		block.blocks.forEach(function(childBlock) {
			var newChildBlock = new AsyncDependenciesBlock(childBlock.name);
			newBlock.addBlock(newChildBlock);
			doBlock(childBlock, newChildBlock);
		});
	}
	doBlock(this, template);
	return template;
};

NormalModule.prototype.getTemplateArguments = function(keepModules) {
	var list = [];
	function doDep(dep) {
		if(dep.module && keepModules.indexOf(dep.module) < 0)
			list.push(dep.module);
	}
	function doVariable(variable) {
		variable.dependencies.forEach(doDep);
	}
	function doBlock(block) {
		block.variables.forEach(doVariable);
		block.dependencies.forEach(doDep);
		block.blocks.forEach(doBlock);
	}
	doBlock(this);
	return list;
};
<commit_msg>edge case where injecting into require.e functions #102<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var Module = require("./Module");
var NormalModuleMixin = require("webpack-core/lib/NormalModuleMixin");
var SourceMapSource = require("webpack-core/lib/SourceMapSource");
var OriginalSource = require("webpack-core/lib/OriginalSource");
var RawSource = require("webpack-core/lib/RawSource");
var ReplaceSource = require("webpack-core/lib/ReplaceSource");
var ModuleParseError = require("./ModuleParseError");
var TemplateArgumentDependency = require("./dependencies/TemplateArgumentDependency");
var path = require("path");

function NormalModule(request, userRequest, rawRequest, loaders, resource, parser) {
	Module.call(this);
	this.request = request;
	this.userRequest = userRequest;
	this.rawRequest = rawRequest;
	this.parser = parser;
	NormalModuleMixin.call(this, loaders, resource);
	this.meta = {};
	this.assets = {};
	this.built = false;
}
module.exports = NormalModule;

NormalModule.prototype = Object.create(Module.prototype);
NormalModuleMixin.mixin(NormalModule.prototype);

NormalModule.prototype.identifier = function() {
	return this.request;
};

NormalModule.prototype.readableIdentifier = function(requestShortener) {
	return requestShortener.shorten(this.userRequest);
};

NormalModule.prototype.fillLoaderContext = function fillLoaderContext(loaderContext, options, compilation) {
	loaderContext.webpack = true;
	compilation.applyPlugins("normal-module-loader", loaderContext);
	loaderContext.emitFile = function(name, content, sourceMap) {
		if(typeof sourceMap === "string") {
			this.assets[name] = new OriginalSource(content, sourceMap);
		} else if(sourceMap) {
			this.assets[name] = new SourceMapSource(content, name, sourceMap);
		} else {
			this.assets[name] = new RawSource(content);
		}
	}.bind(this);
	loaderContext._compilation = compilation;
	loaderContext._compiler = compilation.compiler;
};

NormalModule.prototype.disconnect = function disconnect() {
	this.built = false;
	Module.prototype.disconnect.call(this);
};

NormalModule.prototype.build = function build(options, compilation, resolver, fs, callback) {
	this.buildTimestamp = new Date().getTime();
	this.built = true;
	return this.doBuild(options, compilation, resolver, fs, function(err) {
		if(err) return callback(err);
		try {
			this.parser.parse(this._source.source(), {
				current: this,
				module: this,
				compilation: compilation,
				options: options
			});
		} catch(e) {
			var source = this._source.source();
			this._source = null;
			return callback(new ModuleParseError(this, source, e));
		}
		return callback();
	}.bind(this));
};

NormalModule.prototype.source = function(dependencyTemplates, outputOptions, requestShortener) {
	var _source = this._source;
	if(!_source) return new RawSource("throw new Error('No source availible');");
	var source = new ReplaceSource(_source);
	var topLevelBlock = this;
	function doDep(dep) {
		var template = dependencyTemplates.get(dep.Class);
		if(!template) throw new Error("No template for dependency: " + dep.Class.name);
		template.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
	}
	function doVariable(vars, variable) {
		var name = variable.name;
		var expr = variable.expressionSource(dependencyTemplates, outputOptions, requestShortener);
		vars.push({name: name, expression: expr});
	}
	function doBlock(block) {
		block.dependencies.forEach(doDep);
		block.blocks.forEach(doBlock);
		if(block.variables.length > 0) {
			var vars = [];
			block.variables.forEach(doVariable.bind(null, vars));
			var varNames = [];
			var varExpressions = [];
			var varStartCode = "";
			var varEndCode = "";
			function emitFunction() {
				if(varNames.length == 0) return;

				varStartCode += "/* WEBPACK VAR INJECTION */(function(require, " + varNames.join(", ") + ") {";
				// exports === this in the topLevelBlock, but exports do compress better...
				varEndCode = (topLevelBlock === block ? "}.call(exports, require, " : "}.call(this, require, ") +
					varExpressions.map(function(e) {return e.source()}).join(", ") + "))" + varEndCode;

				varNames.length = 0;
				varExpressions.length = 0;
			}
			vars.forEach(function(v) {
				if(varNames.indexOf(v.name) >= 0) emitFunction();
				varNames.push(v.name);
				varExpressions.push(v.expression);
			});
			emitFunction();
			var start = block.range ? block.range[0] : 0;
			var end = block.range ? block.range[1] : _source.size();
			if(varStartCode) source.insert(start, varStartCode);
			if(varEndCode) source.insert(end, "\n/* WEBPACK VAR INJECTION */" + varEndCode);
		}
	}
	doBlock(this);
	return source;
};

NormalModule.prototype.needRebuild = function needRebuild(fileTimestamps, contextTimestamps) {
	var timestamp = 0;
	this.fileDependencies.forEach(function(file) {
		var ts = fileTimestamps[file];
		if(!ts) timestamp = Infinity;
		if(ts > timestamp) timestamp = ts;
	});
	this.contextDependencies.forEach(function(context) {
		var ts = contextTimestamps[context];
		if(!ts) timestamp = Infinity;
		if(ts > timestamp) timestamp = ts;
	});
	return timestamp >= this.buildTimestamp;
};

NormalModule.prototype.size = function() {
	return this._source ? this._source.size() : -1;
};

NormalModule.prototype.updateHash = function(hash) {
	if(this._source) {
		hash.update("source");
		this._source.updateHash(hash);
	} else
		hash.update("null");
	Module.prototype.updateHash.call(this, hash);
};

NormalModule.prototype.getSourceHash = function() {
	if(!this._source) return "";
	var hash = require("crypto").createHash("md5");
	hash.update(this._source.source());
	return hash.digest("hex");
};

NormalModule.prototype.getAllModuleDependencies = function() {
	var list = [];
	function doDep(dep) {
		if(dep.module && list.indexOf(dep.module) < 0)
			list.push(dep.module);
	}
	function doVariable(variable) {
		variable.dependencies.forEach(doDep);
	}
	function doBlock(block) {
		block.variables.forEach(doVariable);
		block.dependencies.forEach(doDep);
		block.blocks.forEach(doBlock);
	}
	doBlock(this);
	return list;
};

NormalModule.prototype.createTemplate = function(keepModules) {
	var template = new NormalModule("", "", "", [], "", null);
	template._source = this._source;
	template.built = this.built;
	template.templateModules = keepModules;
	var args = template.arguments = [];
	function doDeps(deps) {
		return deps.map(function(dep) {
			if(keepModules.indexOf(dep.module) < 0) {
				var argName = "__webpack_module_template_argument_" + args.length + "__";
				args.push(argName);
				return new TemplateArgumentDependency(argName, dep);
			} else {
				return dep;
			}
		});
	}
	function doVariable(variable, newVariable) {
		variable.dependencies.forEach(doDep);
	}
	function doBlock(block, newBlock) {
		block.variables.forEach(function(variable) {
			var newDependencies = doDeps(variable.dependencies);
			newBlock.addVariable(variable.name, variable.expression, newDependencies);
		});
		newBlock.dependencies = doDeps(block.dependencies);
		block.blocks.forEach(function(childBlock) {
			var newChildBlock = new AsyncDependenciesBlock(childBlock.name);
			newBlock.addBlock(newChildBlock);
			doBlock(childBlock, newChildBlock);
		});
	}
	doBlock(this, template);
	return template;
};

NormalModule.prototype.getTemplateArguments = function(keepModules) {
	var list = [];
	function doDep(dep) {
		if(dep.module && keepModules.indexOf(dep.module) < 0)
			list.push(dep.module);
	}
	function doVariable(variable) {
		variable.dependencies.forEach(doDep);
	}
	function doBlock(block) {
		block.variables.forEach(doVariable);
		block.dependencies.forEach(doDep);
		block.blocks.forEach(doBlock);
	}
	doBlock(this);
	return list;
};
<|endoftext|>


<commit_before>import respawn from 'respawn'

const processes = []

export const processRegister = (command, opts) => {
  const process = respawn(command, opts)

  processes.push(process)

  return process
}

export const processStopAll = (error) => {
  const promises = []
  for (const process of processes) {
    promises.push(
      new Promise((resolve) => {
        if (process.stop) {
          process.stop(resolve)
        } else {
          resolve()
        }
      })
    )
  }
  processes.length = 0

  if (error) {
    // eslint-disable-next-line no-console
    console.error(error)
  }
  return Promise.all(promises)
}

process.on('exit', processStopAll)
<commit_msg>Fix process exit code on error (#2158)<commit_after>import respawn from 'respawn'

const processes = []

export const processRegister = (command, opts) => {
  const process = respawn(command, opts)

  processes.push(process)

  return process
}

const processStopAllListener = (code) => {
  void code
  const promises = []
  for (const process of processes) {
    promises.push(
      new Promise((resolve) => {
        if (process.stop) {
          process.stop(resolve)
        } else {
          resolve()
        }
      })
    )
  }
  processes.length = 0

  return Promise.all(promises)
}

export const processStopAll = (error) => {
  process.removeListener('exit', processStopAllListener)

  if (error != null) {
    // eslint-disable-next-line no-console
    console.error(error)
    if (process.exitCode === undefined || process.exitCode === 0)
      process.exitCode = 1
  }
  return processStopAllListener()
}

process.on('exit', processStopAllListener)
<|endoftext|>