diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -10,10 +10,10 @@
     'conpherence.pkg.css' => '0e3cf785',
     'conpherence.pkg.js' => '020aebcf',
     'core.pkg.css' => '2ba11212',
-    'core.pkg.js' => '66c49ca1',
+    'core.pkg.js' => '2eeda9e0',
     'dark-console.pkg.js' => '187792c2',
     'differential.pkg.css' => '609e63d4',
-    'differential.pkg.js' => 'c60bec1b',
+    'differential.pkg.js' => 'f68ea9d1',
     'diffusion.pkg.css' => '42c75c37',
     'diffusion.pkg.js' => '78c9885d',
     'maniphest.pkg.css' => '35995d6d',
@@ -461,6 +461,7 @@
     'rsrc/js/core/MultirowRowManager.js' => '5b54c823',
     'rsrc/js/core/Notification.js' => 'a9b91e3f',
     'rsrc/js/core/Prefab.js' => '5793d835',
+    'rsrc/js/core/RemarkupMetadata.js' => 'e40c4991',
     'rsrc/js/core/ShapedRequest.js' => '995f5102',
     'rsrc/js/core/TextAreaUtils.js' => 'f340a484',
     'rsrc/js/core/Title.js' => '43bc9360',
@@ -473,7 +474,7 @@
     'rsrc/js/core/behavior-copy.js' => 'cf32921f',
     'rsrc/js/core/behavior-detect-timezone.js' => '78bc5d94',
     'rsrc/js/core/behavior-device.js' => 'ac2b1e01',
-    'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '3277c62d',
+    'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '29e221f6',
     'rsrc/js/core/behavior-fancy-datepicker.js' => 'b545d0a0',
     'rsrc/js/core/behavior-form.js' => '55d7b788',
     'rsrc/js/core/behavior-gesture.js' => 'b58d1a2a',
@@ -489,7 +490,7 @@
     'rsrc/js/core/behavior-more.js' => '506aa3f4',
     'rsrc/js/core/behavior-object-selector.js' => '98ef467f',
     'rsrc/js/core/behavior-oncopy.js' => 'da8f5259',
-    'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '54262396',
+    'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '6d347847',
     'rsrc/js/core/behavior-read-only-warning.js' => 'b9109f8f',
     'rsrc/js/core/behavior-redirect.js' => '407ee861',
     'rsrc/js/core/behavior-refresh-csrf.js' => '46116c01',
@@ -589,7 +590,7 @@
     'javelin-behavior-aphlict-listen' => '4e61fa88',
     'javelin-behavior-aphlict-status' => 'c3703a16',
     'javelin-behavior-aphront-basic-tokenizer' => '3b4899b0',
-    'javelin-behavior-aphront-drag-and-drop-textarea' => '3277c62d',
+    'javelin-behavior-aphront-drag-and-drop-textarea' => '29e221f6',
     'javelin-behavior-aphront-form-disable-on-submit' => '55d7b788',
     'javelin-behavior-aphront-more' => '506aa3f4',
     'javelin-behavior-audio-source' => '3dc5ad43',
@@ -653,7 +654,7 @@
     'javelin-behavior-phabricator-notification-example' => '29819b75',
     'javelin-behavior-phabricator-object-selector' => '98ef467f',
     'javelin-behavior-phabricator-oncopy' => 'da8f5259',
-    'javelin-behavior-phabricator-remarkup-assist' => '54262396',
+    'javelin-behavior-phabricator-remarkup-assist' => '6d347847',
     'javelin-behavior-phabricator-reveal-content' => 'b105a3a6',
     'javelin-behavior-phabricator-search-typeahead' => '1cb7d027',
     'javelin-behavior-phabricator-show-older-transactions' => '8b5c7d65',
@@ -800,6 +801,7 @@
     'phabricator-phtize' => '2f1db1ed',
     'phabricator-prefab' => '5793d835',
     'phabricator-remarkup-css' => '5baa3bd9',
+    'phabricator-remarkup-metadata' => 'e40c4991',
     'phabricator-search-results-css' => '9ea70ace',
     'phabricator-shaped-request' => '995f5102',
     'phabricator-slowvote-css' => '1694baed',
@@ -1163,6 +1165,13 @@
       'javelin-stratcom',
       'javelin-behavior',
     ),
+    '29e221f6' => array(
+      'javelin-behavior',
+      'javelin-dom',
+      'phabricator-drag-and-drop-file-upload',
+      'phabricator-textareautils',
+      'phabricator-remarkup-metadata',
+    ),
     '2a8b62d9' => array(
       'multirow-row-manager',
       'javelin-install',
@@ -1201,13 +1210,6 @@
       'javelin-install',
       'javelin-util',
     ),
-    '3277c62d' => array(
-      'javelin-behavior',
-      'javelin-dom',
-      'javelin-json',
-      'phabricator-drag-and-drop-file-upload',
-      'phabricator-textareautils',
-    ),
     '32db8374' => array(
       'javelin-behavior',
       'javelin-stratcom',
@@ -1424,17 +1426,6 @@
     '541f81c3' => array(
       'javelin-install',
     ),
-    54262396 => array(
-      'javelin-behavior',
-      'javelin-stratcom',
-      'javelin-dom',
-      'phabricator-phtize',
-      'phabricator-textareautils',
-      'javelin-workflow',
-      'javelin-vector',
-      'phuix-autocomplete',
-      'javelin-mask',
-    ),
     '548567f6' => array(
       'syntax-default-css',
     ),
@@ -1575,6 +1566,18 @@
       'javelin-install',
       'javelin-util',
     ),
+    '6d347847' => array(
+      'javelin-behavior',
+      'javelin-stratcom',
+      'javelin-dom',
+      'phabricator-phtize',
+      'phabricator-textareautils',
+      'phabricator-remarkup-metadata',
+      'javelin-workflow',
+      'javelin-vector',
+      'phuix-autocomplete',
+      'javelin-mask',
+    ),
     70245195 => array(
       'javelin-behavior',
       'javelin-stratcom',
@@ -2126,6 +2129,11 @@
       'javelin-dom',
       'phuix-dropdown-menu',
     ),
+    'e40c4991' => array(
+      'javelin-install',
+      'javelin-dom',
+      'javelin-json',
+    ),
     'e4c7622a' => array(
       'javelin-magical-init',
       'javelin-install',
diff --git a/src/view/form/control/PhabricatorRemarkupControl.php b/src/view/form/control/PhabricatorRemarkupControl.php
--- a/src/view/form/control/PhabricatorRemarkupControl.php
+++ b/src/view/form/control/PhabricatorRemarkupControl.php
@@ -128,6 +128,8 @@
         'disabled' => $this->getDisabled(),
         'sendOnEnter' => $this->getSendOnEnter(),
         'rootID' => $root_id,
+        'remarkupMetadataID' => $metadata_id,
+        'remarkupMetadataValue' => $metadata_value,
         'autocompleteMap' => (object)array(
           64 => array( // "@"
             'datasourceURI' => $user_datasource->getDatasourceURI(),
diff --git a/webroot/rsrc/js/core/RemarkupMetadata.js b/webroot/rsrc/js/core/RemarkupMetadata.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/core/RemarkupMetadata.js
@@ -0,0 +1,49 @@
+/**
+ * @requires javelin-install
+ *           javelin-dom
+ *           javelin-json
+ * @provides phabricator-remarkup-metadata
+ * @javelin
+ */
+
+JX.install('RemarkupMetadata', {
+
+  construct: function(metadataValue, metadataID) {
+    if (JX.RemarkupMetadata._metadataValue == null) {
+      JX.RemarkupMetadata._metadataValue = {};
+    }
+    if (!JX.RemarkupMetadata._metadataValue.hasOwnProperty(metadataID)) {
+      JX.RemarkupMetadata._metadataValue[metadataID] = metadataValue;
+    }
+    this._metadataNode = JX.$(metadataID);
+    this._metadataID = metadataID;
+  },
+
+  statics: {
+    _metadataValue: null
+  },
+
+  members: {
+    _metadataNode: null,
+    _metadataID: null,
+
+    _writeMetadata: function() {
+      this._metadataNode.value = JX.JSON.stringify(
+        JX.RemarkupMetadata._metadataValue[this._metadataID]);
+    },
+
+    getMetadata: function(key, default_value) {
+      if (JX.RemarkupMetadata._metadataValue[this._metadataID]
+        .hasOwnProperty(key)) {
+        return JX.RemarkupMetadata._metadataValue[this._metadataID][key];
+      }
+      return default_value;
+    },
+
+    setMetadata: function(key, value) {
+      JX.RemarkupMetadata._metadataValue[this._metadataID][key] = value;
+      this._writeMetadata();
+    }
+  }
+
+});
diff --git a/webroot/rsrc/js/core/behavior-drag-and-drop-textarea.js b/webroot/rsrc/js/core/behavior-drag-and-drop-textarea.js
--- a/webroot/rsrc/js/core/behavior-drag-and-drop-textarea.js
+++ b/webroot/rsrc/js/core/behavior-drag-and-drop-textarea.js
@@ -2,36 +2,15 @@
  * @provides javelin-behavior-aphront-drag-and-drop-textarea
  * @requires javelin-behavior
  *           javelin-dom
- *           javelin-json
  *           phabricator-drag-and-drop-file-upload
  *           phabricator-textareautils
+ *           phabricator-remarkup-metadata
  */
 
 JX.behavior('aphront-drag-and-drop-textarea', function(config) {
 
   var target = JX.$(config.target);
 
-  var metadata_node = JX.$(config.remarkupMetadataID);
-  var metadata_value = config.remarkupMetadataValue;
-
-  function set_metadata(key, value) {
-    metadata_value[key] = value;
-    write_metadata();
-  }
-
-  function get_metadata(key, default_value) {
-    if (metadata_value.hasOwnProperty(key)) {
-      return metadata_value[key];
-    }
-    return default_value;
-  }
-
-  function write_metadata() {
-    metadata_node.value = JX.JSON.stringify(metadata_value);
-  }
-
-  write_metadata();
-
   if (JX.PhabricatorDragAndDropFileUpload.isSupported()) {
     var drop = new JX.PhabricatorDragAndDropFileUpload(target)
       .setURI(config.uri)
@@ -48,9 +27,11 @@
     drop.listen('didUpload', function(file) {
       JX.TextAreaUtils.insertFileReference(target, file);
 
-      var phids = get_metadata('attachedFilePHIDs', []);
+      var metadata = new JX.RemarkupMetadata(config.remarkupMetadataValue,
+        config.remarkupMetadataID);
+      var phids = metadata.getMetadata('attachedFilePHIDs', []);
       phids.push(file.getPHID());
-      set_metadata('attachedFilePHIDs', phids);
+      metadata.setMetadata('attachedFilePHIDs', phids);
     });
 
     drop.start();
diff --git a/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js b/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js
--- a/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js
+++ b/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js
@@ -5,6 +5,7 @@
  *           javelin-dom
  *           phabricator-phtize
  *           phabricator-textareautils
+ *           phabricator-remarkup-metadata
  *           javelin-workflow
  *           javelin-vector
  *           phuix-autocomplete
@@ -255,6 +256,12 @@
                 .setURI(file.uri);
 
               JX.TextAreaUtils.insertFileReference(area, upload);
+
+              var metadata = new JX.RemarkupMetadata(
+                config.remarkupMetadataValue, config.remarkupMetadataID);
+              var phids = metadata.getMetadata('attachedFilePHIDs', []);
+              phids.push(file.phid);
+              metadata.setMetadata('attachedFilePHIDs', phids);
             }
           })
           .start();