diff --git a/app/assets/javascripts/discourse-common/addon/lib/object.js b/app/assets/javascripts/discourse-common/addon/lib/object.js index b34594e81e1..e90cf267af7 100644 --- a/app/assets/javascripts/discourse-common/addon/lib/object.js +++ b/app/assets/javascripts/discourse-common/addon/lib/object.js @@ -1,9 +1,9 @@ -// a fairly simple deep merge based on: https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6 function isObject(obj) { return obj && typeof obj === "object"; } -export function merge(...objects) { +// a fairly simple deep merge based on: https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6 +export function deepMerge(...objects) { function deepMergeInner(target, source) { Object.keys(source).forEach(key => { const targetValue = target[key]; diff --git a/app/assets/javascripts/discourse/app/controllers/topic.js b/app/assets/javascripts/discourse/app/controllers/topic.js index be9b7e9598b..f6eead81269 100644 --- a/app/assets/javascripts/discourse/app/controllers/topic.js +++ b/app/assets/javascripts/discourse/app/controllers/topic.js @@ -26,7 +26,7 @@ import { escapeExpression } from "discourse/lib/utilities"; import { AUTO_DELETE_PREFERENCES } from "discourse/models/bookmark"; import { inject as service } from "@ember/service"; import bootbox from "bootbox"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; let customPostMessageCallbacks = {}; @@ -250,7 +250,7 @@ export default Controller.extend(bufferedProperty("model"), { this.set("loadingPostIds", true); return ajax(url, { - data: merge( + data: deepMerge( { post_number: post.get("post_number") }, postStream.get("streamFilters") ) diff --git a/app/assets/javascripts/discourse/app/lib/search.js b/app/assets/javascripts/discourse/app/lib/search.js index c91677bff41..53d14d2e1bc 100644 --- a/app/assets/javascripts/discourse/app/lib/search.js +++ b/app/assets/javascripts/discourse/app/lib/search.js @@ -13,7 +13,7 @@ import User from "discourse/models/user"; import Post from "discourse/models/post"; import Topic from "discourse/models/topic"; import { escapeExpression } from "discourse/lib/utilities"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; export function translateResults(results, opts) { opts = opts || {}; @@ -207,7 +207,7 @@ export function applySearchAutocomplete( }; $input.autocomplete( - merge( + deepMerge( { template: findRawTemplate("category-tag-autocomplete"), key: "#", @@ -227,7 +227,7 @@ export function applySearchAutocomplete( if (siteSettings.enable_mentions) { $input.autocomplete( - merge( + deepMerge( { template: findRawTemplate("user-selector-autocomplete"), key: "@", diff --git a/app/assets/javascripts/discourse/app/lib/utilities.js b/app/assets/javascripts/discourse/app/lib/utilities.js index 946e12f3a5f..a5ee007cca3 100644 --- a/app/assets/javascripts/discourse/app/lib/utilities.js +++ b/app/assets/javascripts/discourse/app/lib/utilities.js @@ -4,7 +4,7 @@ import toMarkdown from "discourse/lib/to-markdown"; import Handlebars from "handlebars"; import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url"; import { helperContext } from "discourse-common/lib/helpers"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; let _defaultHomepage; @@ -86,7 +86,7 @@ export function avatarImg(options, customGetURL) { export function tinyAvatar(avatarTemplate, options) { return avatarImg( - merge({ avatarTemplate: avatarTemplate, size: "tiny" }, options) + deepMerge({ avatarTemplate: avatarTemplate, size: "tiny" }, options) ); } diff --git a/app/assets/javascripts/discourse/app/mixins/upload.js b/app/assets/javascripts/discourse/app/mixins/upload.js index 2846ce38953..a71863354fb 100644 --- a/app/assets/javascripts/discourse/app/mixins/upload.js +++ b/app/assets/javascripts/discourse/app/mixins/upload.js @@ -8,7 +8,7 @@ import getUrl from "discourse-common/lib/get-url"; import { on } from "@ember/object/evented"; import Mixin from "@ember/object/mixin"; import bootbox from "bootbox"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; export default Mixin.create({ uploading: false, @@ -57,7 +57,7 @@ export default Mixin.create({ }); $upload.fileupload( - merge( + deepMerge( { url: this.calculateUploadUrl(), dataType: "json", @@ -83,7 +83,7 @@ export default Mixin.create({ }); $upload.on("fileuploadsubmit", (e, data) => { - const opts = merge( + const opts = deepMerge( { bypassNewUserRestriction: true, user: this.currentUser, diff --git a/app/assets/javascripts/discourse/app/models/nav-item.js b/app/assets/javascripts/discourse/app/models/nav-item.js index 8c8bb5b9592..bbd89744939 100644 --- a/app/assets/javascripts/discourse/app/models/nav-item.js +++ b/app/assets/javascripts/discourse/app/models/nav-item.js @@ -9,7 +9,7 @@ import deprecated from "discourse-common/lib/deprecated"; import Site from "discourse/models/site"; import User from "discourse/models/user"; import { getOwner } from "discourse-common/lib/get-owner"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; const NavItem = EmberObject.extend({ @discourseComputed("name") @@ -181,7 +181,7 @@ NavItem.reopenClass({ args.noSubcategories = true; } NavItem.extraArgsCallbacks.forEach(cb => - merge(args, cb.call(this, filterType, opts)) + deepMerge(args, cb.call(this, filterType, opts)) ); let store = getOwner(this).lookup("service:store"); @@ -223,7 +223,9 @@ NavItem.reopenClass({ }; const extraItems = NavItem.extraNavItemDescriptors - .map(descriptor => ExtraNavItem.create(merge({}, context, descriptor))) + .map(descriptor => + ExtraNavItem.create(deepMerge({}, context, descriptor)) + ) .filter(item => { if (!item.customFilter) return true; return item.customFilter(category, args); diff --git a/app/assets/javascripts/discourse/app/models/post-stream.js b/app/assets/javascripts/discourse/app/models/post-stream.js index f2036ff77b2..faec52687ee 100644 --- a/app/assets/javascripts/discourse/app/models/post-stream.js +++ b/app/assets/javascripts/discourse/app/models/post-stream.js @@ -10,7 +10,7 @@ import discourseComputed from "discourse-common/utils/decorators"; import { loadTopicView } from "discourse/models/topic"; import { Promise } from "rsvp"; import User from "discourse/models/user"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; export default RestModel.extend({ _identityMap: null, @@ -275,7 +275,7 @@ export default RestModel.extend({ this.set("loadingFilter", true); this.set("loadingNearPost", opts.nearPost); - opts = merge(opts, this.streamFilters); + opts = deepMerge(opts, this.streamFilters); // Request a topicView return loadTopicView(topic, opts) @@ -944,7 +944,7 @@ export default RestModel.extend({ include_suggested: includeSuggested }; - data = merge(data, this.streamFilters); + data = deepMerge(data, this.streamFilters); const store = this.store; return ajax(url, { data }).then(result => { diff --git a/app/assets/javascripts/discourse/app/models/topic.js b/app/assets/javascripts/discourse/app/models/topic.js index 56d1cce2046..751baf3c276 100644 --- a/app/assets/javascripts/discourse/app/models/topic.js +++ b/app/assets/javascripts/discourse/app/models/topic.js @@ -23,10 +23,10 @@ import { Promise } from "rsvp"; import Site from "discourse/models/site"; import User from "discourse/models/user"; import bootbox from "bootbox"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; export function loadTopicView(topic, args) { - const data = merge({}, args); + const data = deepMerge({}, args); const url = `${getURL("/t/")}${topic.id}`; const jsonUrl = (data.nearPost ? `${url}/${data.nearPost}` : url) + ".json"; diff --git a/app/assets/javascripts/discourse/app/routes/invites-show.js b/app/assets/javascripts/discourse/app/routes/invites-show.js index ceee8c0030f..033da82deb6 100644 --- a/app/assets/javascripts/discourse/app/routes/invites-show.js +++ b/app/assets/javascripts/discourse/app/routes/invites-show.js @@ -1,7 +1,7 @@ import I18n from "I18n"; import DiscourseRoute from "discourse/routes/discourse"; import PreloadStore from "discourse/lib/preload-store"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; export default DiscourseRoute.extend({ titleToken() { @@ -11,7 +11,7 @@ export default DiscourseRoute.extend({ model(params) { if (PreloadStore.get("invite_info")) { return PreloadStore.getAndRemove("invite_info").then(json => - merge(params, json) + deepMerge(params, json) ); } else { return {}; diff --git a/app/assets/javascripts/discourse/app/routes/password-reset.js b/app/assets/javascripts/discourse/app/routes/password-reset.js index 225e17170c8..546aecfcf4f 100644 --- a/app/assets/javascripts/discourse/app/routes/password-reset.js +++ b/app/assets/javascripts/discourse/app/routes/password-reset.js @@ -3,7 +3,7 @@ import DiscourseRoute from "discourse/routes/discourse"; import PreloadStore from "discourse/lib/preload-store"; import { ajax } from "discourse/lib/ajax"; import { userPath } from "discourse/lib/url"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; export default DiscourseRoute.extend({ titleToken() { @@ -13,7 +13,7 @@ export default DiscourseRoute.extend({ model(params) { if (PreloadStore.get("password_reset")) { return PreloadStore.getAndRemove("password_reset").then(json => - merge(params, json) + deepMerge(params, json) ); } }, diff --git a/app/assets/javascripts/discourse/app/widgets/topic-timeline.js b/app/assets/javascripts/discourse/app/widgets/topic-timeline.js index 088e8a7a181..8ed1c046845 100644 --- a/app/assets/javascripts/discourse/app/widgets/topic-timeline.js +++ b/app/assets/javascripts/discourse/app/widgets/topic-timeline.js @@ -8,7 +8,7 @@ import { iconNode } from "discourse-common/lib/icon-library"; import RawHtml from "discourse/widgets/raw-html"; import renderTags from "discourse/lib/render-tags"; import renderTopicFeaturedLink from "discourse/lib/render-topic-featured-link"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; const SCROLLER_HEIGHT = 50; const LAST_READ_HEIGHT = 20; @@ -241,7 +241,7 @@ createWidget("timeline-scrollarea", { this.attach("timeline-padding", { height: before }), this.attach( "timeline-scroller", - merge(position, { + deepMerge(position, { showDockedButton: !attrs.mobileView && hasBackPosition && !showButton, fullScreen: attrs.fullScreen }) diff --git a/app/assets/javascripts/discourse/app/widgets/widget.js b/app/assets/javascripts/discourse/app/widgets/widget.js index e5af7a68a7c..ef14ad5098b 100644 --- a/app/assets/javascripts/discourse/app/widgets/widget.js +++ b/app/assets/javascripts/discourse/app/widgets/widget.js @@ -22,7 +22,7 @@ import DecoratorHelper from "discourse/widgets/decorator-helper"; import { Promise } from "rsvp"; import { isProduction } from "discourse-common/config/environment"; import { get } from "@ember/object"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; const _registry = {}; @@ -186,7 +186,7 @@ export default class Widget { // Sometimes we pass state down from the parent if (this.mergeState) { - this.state = merge(this.state, this.mergeState); + this.state = deepMerge(this.state, this.mergeState); } if (prev) { diff --git a/app/assets/javascripts/pretty-text/addon/pretty-text.js b/app/assets/javascripts/pretty-text/addon/pretty-text.js index 8114a4471cb..38df7882fb8 100644 --- a/app/assets/javascripts/pretty-text/addon/pretty-text.js +++ b/app/assets/javascripts/pretty-text/addon/pretty-text.js @@ -2,7 +2,7 @@ import { cook as cookIt, setup as setupIt } from "pretty-text/engines/discourse-markdown-it"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; export function registerOption() { // TODO next major version deprecate this @@ -49,7 +49,7 @@ export function buildOptions(state) { }; if (state.features) { - features = merge(features, state.features); + features = deepMerge(features, state.features); } const options = { diff --git a/test/javascripts/lib/pretty-text-test.js b/test/javascripts/lib/pretty-text-test.js index 71fbdbe7243..6bda27b097c 100644 --- a/test/javascripts/lib/pretty-text-test.js +++ b/test/javascripts/lib/pretty-text-test.js @@ -8,7 +8,7 @@ import { } from "pretty-text/inline-oneboxer"; import { extractDataAttribute } from "pretty-text/engines/discourse-markdown-it"; import { registerEmoji } from "pretty-text/emoji"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; QUnit.module("lib:pretty-text"); @@ -39,7 +39,7 @@ QUnit.assert.cooked = function(input, expected, message) { }; QUnit.assert.cookedOptions = function(input, opts, expected, message) { - const merged = merge({}, rawOpts, opts); + const merged = deepMerge({}, rawOpts, opts); const actual = new PrettyText(buildOptions(merged)).cook(input); this.pushResult({ result: actual === expected, diff --git a/test/javascripts/models/post-test.js b/test/javascripts/models/post-test.js index 1f62cafbe54..e878dbabc65 100644 --- a/test/javascripts/models/post-test.js +++ b/test/javascripts/models/post-test.js @@ -1,12 +1,12 @@ import Post from "discourse/models/post"; import User from "discourse/models/user"; -import { merge } from "discourse-common/lib/object"; +import { deepMerge } from "discourse-common/lib/object"; QUnit.module("model: Post"); var buildPost = function(args) { return Post.create( - merge( + deepMerge( { id: 1, can_delete: true,