Factor out cloning to a util and use it everywhere
This commit is contained in:
parent
9e3c101172
commit
1fe3e33dbf
9 changed files with 29 additions and 13 deletions
|
@ -25,6 +25,7 @@ import RoomViewStore from "./stores/RoomViewStore";
|
||||||
import {IntegrationManagers} from "./integrations/IntegrationManagers";
|
import {IntegrationManagers} from "./integrations/IntegrationManagers";
|
||||||
import SettingsStore from "./settings/SettingsStore";
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
import {Capability} from "./widgets/WidgetApi";
|
import {Capability} from "./widgets/WidgetApi";
|
||||||
|
import {objectClone} from "./utils/objects";
|
||||||
|
|
||||||
const WIDGET_API_VERSION = '0.0.2'; // Current API version
|
const WIDGET_API_VERSION = '0.0.2'; // Current API version
|
||||||
const SUPPORTED_WIDGET_API_VERSIONS = [
|
const SUPPORTED_WIDGET_API_VERSIONS = [
|
||||||
|
@ -247,7 +248,7 @@ export default class FromWidgetPostMessageApi {
|
||||||
* @param {Object} res Response data
|
* @param {Object} res Response data
|
||||||
*/
|
*/
|
||||||
sendResponse(event, res) {
|
sendResponse(event, res) {
|
||||||
const data = JSON.parse(JSON.stringify(event.data));
|
const data = objectClone(event.data);
|
||||||
data.response = res;
|
data.response = res;
|
||||||
event.source.postMessage(data, event.origin);
|
event.source.postMessage(data, event.origin);
|
||||||
}
|
}
|
||||||
|
@ -260,7 +261,7 @@ export default class FromWidgetPostMessageApi {
|
||||||
*/
|
*/
|
||||||
sendError(event, msg, nestedError) {
|
sendError(event, msg, nestedError) {
|
||||||
console.error('Action:' + event.data.action + ' failed with message: ' + msg);
|
console.error('Action:' + event.data.action + ' failed with message: ' + msg);
|
||||||
const data = JSON.parse(JSON.stringify(event.data));
|
const data = objectClone(event.data);
|
||||||
data.response = {
|
data.response = {
|
||||||
error: {
|
error: {
|
||||||
message: msg,
|
message: msg,
|
||||||
|
|
|
@ -244,16 +244,17 @@ import RoomViewStore from './stores/RoomViewStore';
|
||||||
import { _t } from './languageHandler';
|
import { _t } from './languageHandler';
|
||||||
import {IntegrationManagers} from "./integrations/IntegrationManagers";
|
import {IntegrationManagers} from "./integrations/IntegrationManagers";
|
||||||
import {WidgetType} from "./widgets/WidgetType";
|
import {WidgetType} from "./widgets/WidgetType";
|
||||||
|
import {objectClone} from "./utils/objects";
|
||||||
|
|
||||||
function sendResponse(event, res) {
|
function sendResponse(event, res) {
|
||||||
const data = JSON.parse(JSON.stringify(event.data));
|
const data = objectClone(event.data);
|
||||||
data.response = res;
|
data.response = res;
|
||||||
event.source.postMessage(data, event.origin);
|
event.source.postMessage(data, event.origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendError(event, msg, nestedError) {
|
function sendError(event, msg, nestedError) {
|
||||||
console.error("Action:" + event.data.action + " failed with message: " + msg);
|
console.error("Action:" + event.data.action + " failed with message: " + msg);
|
||||||
const data = JSON.parse(JSON.stringify(event.data));
|
const data = objectClone(event.data);
|
||||||
data.response = {
|
data.response = {
|
||||||
error: {
|
error: {
|
||||||
message: msg,
|
message: msg,
|
||||||
|
|
|
@ -18,6 +18,7 @@ import React from "react";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import {_t, pickBestLanguage} from "../../../languageHandler";
|
import {_t, pickBestLanguage} from "../../../languageHandler";
|
||||||
import * as sdk from "../../..";
|
import * as sdk from "../../..";
|
||||||
|
import {objectClone} from "../../../utils/objects";
|
||||||
|
|
||||||
export default class InlineTermsAgreement extends React.Component {
|
export default class InlineTermsAgreement extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -56,7 +57,7 @@ export default class InlineTermsAgreement extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
_togglePolicy = (index) => {
|
_togglePolicy = (index) => {
|
||||||
const policies = JSON.parse(JSON.stringify(this.state.policies)); // deep & cheap clone
|
const policies = objectClone(this.state.policies);
|
||||||
policies[index].checked = !policies[index].checked;
|
policies[index].checked = !policies[index].checked;
|
||||||
this.setState({policies});
|
this.setState({policies});
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
||||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||||
import {SettingLevel} from "../SettingsStore";
|
import {SettingLevel} from "../SettingsStore";
|
||||||
import {objectKeyChanges} from "../../utils/objects";
|
import {objectClone, objectKeyChanges} from "../../utils/objects";
|
||||||
|
|
||||||
const BREADCRUMBS_LEGACY_EVENT_TYPE = "im.vector.riot.breadcrumb_rooms";
|
const BREADCRUMBS_LEGACY_EVENT_TYPE = "im.vector.riot.breadcrumb_rooms";
|
||||||
const BREADCRUMBS_EVENT_TYPE = "im.vector.setting.breadcrumbs";
|
const BREADCRUMBS_EVENT_TYPE = "im.vector.setting.breadcrumbs";
|
||||||
|
@ -162,7 +162,7 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
|
||||||
|
|
||||||
const event = cli.getAccountData(eventType);
|
const event = cli.getAccountData(eventType);
|
||||||
if (!event || !event.getContent()) return null;
|
if (!event || !event.getContent()) return null;
|
||||||
return JSON.parse(JSON.stringify(event.getContent())); // clone to prevent mutation
|
return objectClone(event.getContent()); // clone to prevent mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
_notifyBreadcrumbsUpdate(event) {
|
_notifyBreadcrumbsUpdate(event) {
|
||||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
||||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||||
import {SettingLevel} from "../SettingsStore";
|
import {SettingLevel} from "../SettingsStore";
|
||||||
import {objectKeyChanges} from "../../utils/objects";
|
import {objectClone, objectKeyChanges} from "../../utils/objects";
|
||||||
|
|
||||||
const ALLOWED_WIDGETS_EVENT_TYPE = "im.vector.setting.allowed_widgets";
|
const ALLOWED_WIDGETS_EVENT_TYPE = "im.vector.setting.allowed_widgets";
|
||||||
|
|
||||||
|
@ -137,6 +137,6 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
|
||||||
|
|
||||||
const event = room.getAccountData(eventType);
|
const event = room.getAccountData(eventType);
|
||||||
if (!event || !event.getContent()) return null;
|
if (!event || !event.getContent()) return null;
|
||||||
return event.getContent();
|
return objectClone(event.getContent()); // clone to prevent mutation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
||||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||||
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
|
||||||
import {SettingLevel} from "../SettingsStore";
|
import {SettingLevel} from "../SettingsStore";
|
||||||
import {objectKeyChanges} from "../../utils/objects";
|
import {objectClone, objectKeyChanges} from "../../utils/objects";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets and sets settings at the "room" level.
|
* Gets and sets settings at the "room" level.
|
||||||
|
@ -117,6 +117,6 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl
|
||||||
|
|
||||||
const event = room.currentState.getStateEvents(eventType, "");
|
const event = room.currentState.getStateEvents(eventType, "");
|
||||||
if (!event || !event.getContent()) return null;
|
if (!event || !event.getContent()) return null;
|
||||||
return event.getContent();
|
return objectClone(event.getContent()); // clone to prevent mutation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import {IntegrationManagers} from "../integrations/IntegrationManagers";
|
||||||
import {Capability} from "../widgets/WidgetApi";
|
import {Capability} from "../widgets/WidgetApi";
|
||||||
import {Room} from "matrix-js-sdk/src/models/room";
|
import {Room} from "matrix-js-sdk/src/models/room";
|
||||||
import {WidgetType} from "../widgets/WidgetType";
|
import {WidgetType} from "../widgets/WidgetType";
|
||||||
|
import {objectClone} from "./objects";
|
||||||
|
|
||||||
export default class WidgetUtils {
|
export default class WidgetUtils {
|
||||||
/* Returns true if user is able to send state events to modify widgets in this room
|
/* Returns true if user is able to send state events to modify widgets in this room
|
||||||
|
@ -222,7 +223,7 @@ export default class WidgetUtils {
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
// Get the current widgets and clone them before we modify them, otherwise
|
// Get the current widgets and clone them before we modify them, otherwise
|
||||||
// we'll modify the content of the old event.
|
// we'll modify the content of the old event.
|
||||||
const userWidgets = JSON.parse(JSON.stringify(WidgetUtils.getUserWidgets()));
|
const userWidgets = objectClone(WidgetUtils.getUserWidgets());
|
||||||
|
|
||||||
// Delete existing widget with ID
|
// Delete existing widget with ID
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -47,3 +47,14 @@ export function objectKeyChanges(a: any, b: any): string[] {
|
||||||
const diff = objectDiff(a, b);
|
const diff = objectDiff(a, b);
|
||||||
return arrayMerge(diff.removed, diff.added, diff.changed);
|
return arrayMerge(diff.removed, diff.added, diff.changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clones an object by running it through JSON parsing. Note that this
|
||||||
|
* will destroy any complicated object types which do not translate to
|
||||||
|
* JSON.
|
||||||
|
* @param obj The object to clone.
|
||||||
|
* @returns The cloned object
|
||||||
|
*/
|
||||||
|
export function objectClone(obj: any): any {
|
||||||
|
return JSON.parse(JSON.stringify(obj));
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ limitations under the License.
|
||||||
|
|
||||||
import { randomString } from "matrix-js-sdk/src/randomstring";
|
import { randomString } from "matrix-js-sdk/src/randomstring";
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
|
import { objectClone } from "../utils/objects";
|
||||||
|
|
||||||
export enum Capability {
|
export enum Capability {
|
||||||
Screenshot = "m.capability.screenshot",
|
Screenshot = "m.capability.screenshot",
|
||||||
|
@ -140,7 +141,7 @@ export class WidgetApi extends EventEmitter {
|
||||||
private replyToRequest(payload: ToWidgetRequest, reply: any) {
|
private replyToRequest(payload: ToWidgetRequest, reply: any) {
|
||||||
if (!window.parent) return;
|
if (!window.parent) return;
|
||||||
|
|
||||||
const request = JSON.parse(JSON.stringify(payload));
|
const request = objectClone(payload);
|
||||||
request.response = reply;
|
request.response = reply;
|
||||||
|
|
||||||
window.parent.postMessage(request, this.origin);
|
window.parent.postMessage(request, this.origin);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue