123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
- const constants = require("../constants");
- /**
- * Initial state definition
- */
- function getInitialState() {
- return new Map();
- }
- /**
- * Maintain a cache of received grip responses from the backend.
- */
- function grips(state = getInitialState(), action) {
- // This reducer supports only one action, fetching actor properties
- // from the backend so, bail out if we are dealing with any other
- // action.
- if (action.type != constants.FETCH_PROPERTIES) {
- return state;
- }
- switch (action.status) {
- case "start":
- return onRequestProperties(state, action);
- case "end":
- return onReceiveProperties(state, action);
- }
- return state;
- }
- /**
- * Handle requestProperties action
- */
- function onRequestProperties(state, action) {
- return state;
- }
- /**
- * Handle receiveProperties action
- */
- function onReceiveProperties(cache, action) {
- let response = action.response;
- let from = response.from;
- let className = action.grip.class;
- // Properly deal with getters.
- mergeProperties(response);
- // Compute list of requested children.
- let previewProps = response.preview ? response.preview.ownProperties : null;
- let ownProps = response.ownProperties || previewProps || [];
- let props = Object.keys(ownProps).map(key => {
- // Array indexes as a special case. We convert any keys that are string
- // representations of integers to integers.
- if (className === "Array" && isInteger(key)) {
- key = parseInt(key, 10);
- }
- return new Property(key, ownProps[key], key);
- });
- props.sort(sortName);
- // Return new state/map.
- let newCache = new Map(cache);
- newCache.set(from, props);
- return newCache;
- }
- // Helpers
- function mergeProperties(response) {
- let { ownProperties } = response;
- // 'safeGetterValues' is new and isn't necessary defined on old grips.
- let safeGetterValues = response.safeGetterValues || {};
- // Merge the safe getter values into one object such that we can use it
- // in variablesView.
- for (let name of Object.keys(safeGetterValues)) {
- if (name in ownProperties) {
- let { getterValue, getterPrototypeLevel } = safeGetterValues[name];
- ownProperties[name].getterValue = getterValue;
- ownProperties[name].getterPrototypeLevel = getterPrototypeLevel;
- } else {
- ownProperties[name] = safeGetterValues[name];
- }
- }
- }
- function sortName(a, b) {
- // Display non-enumerable properties at the end.
- if (!a.value.enumerable && b.value.enumerable) {
- return 1;
- }
- if (a.value.enumerable && !b.value.enumerable) {
- return -1;
- }
- return a.name > b.name ? 1 : -1;
- }
- function isInteger(n) {
- // We use parseInt(n, 10) == n to disregard scientific notation e.g. "3e24"
- return isFinite(n) && parseInt(n, 10) == n;
- }
- function Property(name, value, key) {
- this.name = name;
- this.value = value;
- this.key = key;
- }
- // Exports from this module
- exports.grips = grips;
- exports.Property = Property;
|