1

After setting a uuid4 object property either by the Object.assign or Object.defineProperty methods, the property sometimes unsets itself in Safari without explanation, as in the following minimal reproducible example.

I have not observed this issue in Chrome.

To reproduce using this example on a local machine, I would click the "Choose Files" buttons and select files from my local file system. The script preview-uploads.js will then assign the uuid4 property, which uploads-manager.js will subsequently attempt to read and print to console with console.log(file.uuid4).

The example uses local files, so you'll need to disable local file restrictions in Safari as described here to run this example.

The issue occurs inconsistently in this minimum reproducible example. It took me about 20-30 trials before it occurred again, as confirmed by the screenshot below which shows how console.log(file.uuid4) printed "undefined" to the console. However, in the complicated use case where I am applying it (and which is too big and proprietary to post), it happens nine times out of ten.

There is no obvious pattern that I observe. I've paid attention to the file types and file sizes that I'm experimenting with, and the issue bears no obvious correlation to either.

Can someone please help me understand what is causing the property to unset in this apparently random way?

(By the way, the ajax method of building the html is important to my proprietary use case, which is why I've included it in the MRE.)

Screenshot

enter image description here

test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.6.0.js"></script>
</head>
<body>
</body>
<script>
    $(document).ready(function () {
        $.ajax({
            type: 'GET',
            url: 'file:///path/to/test_ajax.html',
            success: function (response) {
                $('body').html(response);
            }
        })
    });
</script>
</html>

test_ajax.html

<script src="/path/to/preview-uploads.js"></script>
<div>
    <div id="files-test1">
        <input autocomplete="off" multiple="true" name="files[]"
               onchange="previewFiles('test1');uploadFiles()" type="file">
    </div>
    <div class="grid-test1 padding-top-15" data-uuid4list="">
        <a href="" target="_blank"><img/>
        </a>
    </div>
</div>
<div>
    <div id="files-test2">
        <input autocomplete="off" multiple="true" name="files[]"
               onchange="previewFiles('test2');uploadFiles()" type="file">
    </div>
    <div class="grid-test2 padding-top-15" data-uuid4list="">
        <a href="" target="_blank">
            <img/>
        </a>
    </div>
</div>
<script src="/path/to/upload-manager.js"></script>

preview-uploads.js

function previewFiles(fileId) {
  var files   = document.querySelector('[id="files-' + fileId.replace('.','\\.') + '"]>input').files;

  if (files) {
    [].forEach.call(files, function(file) {
      let uuid4 = '09832a0d-86c4-4a9f-ab93-23bac596b83b';
      Object.assign(file, {'uuid4': uuid4});
    });
  };
};

upload-manager.js

function uploadFiles() {
    var formData = new FormData();
    $("input[type='file']").each(function() {
        $.each(this.files, function(i, file) {
            formData.append('files[]', file, file.uuid4 + ':' + file.name);
            console.log('file.uuid4 will follow next');
            console.log(file.uuid4);
        });
    });
};
Bryton Beesley
  • 167
  • 2
  • 12
  • 1
    not sure but shouldnt you assign the return value of Object.assign sth like: `file = Object.assign(file, {'uuid4': uuid4}); })` – john Smith Jan 23 '23 at 08:44
  • 1
    Thanks, @johnSmith, for commenting. I don't think the assignment is required, but I tested the idea just to confirm. Nevertheless, the property is still unsetting itself. – Bryton Beesley Jan 23 '23 at 17:44
  • 1
    i tried it out and can verify the same result, sometimes it is `undefined` in safari and i cant see any pattern when or why it does. – john Smith Jan 23 '23 at 22:35
  • The first thing I'd check is to make sure the `files` returned in `uploadFiles` is the same collection of `files` returned in `previewFiles`, e.g., the browser isn't creating a new `FileList` or something. Is the UUID necessary before `uploadFiles`, e.g., can the UUID be added immediate before submission? (Totally unrelated, but why not `file.uuid4 = uuid4`?) – Dave Newton Feb 01 '23 at 16:52
  • Thanks, @Dave Newton, for the suggestion. I'm not sure how one would check that, but the way I attempted to do so was by inspecting the `lastModified` property of `files`. It remained the same between the `previewFiles` and `uploadFiles` functions, suggesting that both are operating on the same collection. (Regarding `file.uuid4 = uuid4`, that's a legitimate way to set the object's property but doesn't solve the issue, unfortunately.) – Bryton Beesley Feb 01 '23 at 21:04

0 Answers0