Folder.getFiles() Bug

A Listing of Confirmed Scripting Bugs and Anomalies - Open to all but only moderators can post

Moderators: xbytor, DavideBarranca, Paul MR

xbytor

Folder.getFiles() Bug

Post by xbytor »

There is a bug in the Folder.getFiles() object method.

Versions:
PS7 - broke (need to reconfirm testcase)
PSCS - broke (confirmed)
PSCS2 - fixed for testcaseDetails:
This bug occurs when
Folder.getFiles() is invoked
and a filter function is used (instead of a mask)
and the folder contains a lot of files (e.g. > 70)
and the filter function returns a subset of the filesThis bug does not occur when
using a file mask (e.g. "biz_*.jpg")
all files are returned
no files are returned

Results:
The call to Folder.getFiles() will fail. After this failure, any attempt to execute any script will fail requiring a restart of PS.

Here is a testcase for this bug.
Code: Select all//
// Test Case for Folder.getFiles()
//    Put 70 to 80 files in one directory
//    Point Options.folderPath to that directory
//    Set Options.maxLength such that some file pathnames
//    are longer and other are shorter
//    This testcase does not require any images to run

function Options() {}

Options.folderPath = "/h/New/1test";
Options.str = '';
Options.maxLength = 30;

function filter(s) {
  Options.str += (s.toString().length + '\r\n');
  //$.writeln(Options.str);
  //alert(s.toString().length);
  return s.toString().length < Options.maxLength;
}

var f = new Folder(Options.folderPath);

try {
  var s  = f.getFiles(filter).length;
  alert(s);
  Options.str += s;
  //$.writeln(Options.str);
} catch (e) {
  alert(e);
}

I have a fix for this that I will post in a day or two (after more testing) with the subject Folder.getFiles() Bug Workaround

xbytor

Folder.getFiles() Bug

Post by xbytor »

Ooops. Forgot I left this hanging.
Here's what I have in my library. It fixes the bug in PS7 and CS and adds support for Regular Expression matching.

Code: Select all//
// Adds RegExp support. Avoids PS7/CS bug in Folder.getFiles()
// usage:
//    getFiles(folder);
//    getFiles(folder, "*.jpg");
//    getFiles(folder, /\.jpg$/);
//    getFiles(folder, function(f) { return f instanceof Folder; });
//
getFiles = function(folder, mask) {
  var files = [];

  if (mask instanceof RegExp) {
    var allFiles = folder.getFiles();
    for (var i = 0; i < allFiles.length; i = i + 1) {
      var f = allFiles;
      if (decodeURI(f.absoluteURI).match(mask)) {
        files.push(f);
      }
    }
  } else if (typeof mask == "function") {
    var allFiles = folder.getFiles();
    for (var i = 0; i < allFiles.length; i = i + 1) {
      var f = allFiles;
      if (mask(f)) {
        files.push(f);
      }
    }
  } else {
    files = folder.getFiles(mask);
  }

  return files;
}


If anyone's interested, I'll write up the code to install it in place of the exiting Folder.getFiles implementation.

Andrew

Folder.getFiles() Bug

Post by Andrew »

Yes I am definitely interested, thanks for this Xbytor.

BTW, earlier this year you made available XTools in the Adobe forum. I have a bit more time free now I am back from Australia and I'd love to have a look at it again if possible.

Andrew

xbytor

Folder.getFiles() Bug

Post by xbytor »

I've been kicking around several techniques for swapping in new versions of methods on existing JS or PSJS classes. I like this one because it lets me wrap an existing method with little or no change, provides install/uninstall calls, and keeps a handle to the original implementation if it is still needed. I'll see if I can find time to write up a tutorial for this a bit later.

Note that you have to add an explicit call to Stdlib.getFiles.install() to get Folder.getFiles replaced.

Code: Select all//
// Adds RegExp support and avoids PS7/CS bug in Folder.getFiles()
// usage:
//    getFiles(folder);
//    getFiles(folder, "*.jpg");
//    getFiles(folder, /\.jpg$/);
//    getFiles(folder, function(f) { return f instanceof Folder; });
//
Stdlib.getFiles = function(folder, mask) {
  var files = [];

  Stdlib.fullStop();
  var getF;
  if (Folder.prototype._getFiles) {
    getF = function(f, m) { return f._getFiles(m); }
  } else {
    getF = function(f, m) { return f.getFiles(m); }
  }

  if (mask instanceof RegExp) {
    var allFiles = getF(folder);
    for (var i = 0; i < allFiles.length; i = i + 1) {
      var f = allFiles;
      if (decodeURI(f.absoluteURI).match(mask)) {
        files.push(f);
      }
    }
  } else if (typeof mask == "function") {
    var allFiles = getF(folder);
    for (var i = 0; i < allFiles.length; i = i + 1) {
      var f = allFiles;
      if (mask(f)) {
        files.push(f);
      }
    }
  } else {
    files = getF(folder, mask);
  }

  return files;
}

//
// Install a an adaptor to that our getFiles code will be invoked when Folder.getFiles is called.
// The difficulty here is that we need to retain a handle to the original implementation so that we
// can invoke it from our version.
//
Stdlib.getFiles.install = function() {
  if (!Folder.prototype._getFiles) {
    Folder.prototype._getFiles = Folder.prototype.getFiles; // save the original getFiles
    Folder.prototype.getFiles = function(mask) {            // slide in an adaptor for our version
      return Stdlib.getFiles(this, mask);
    }
  }
}
//
// Remove our adaptor and restore the original Folder.getFiles method
//
Stdlib.getFiles.uninstall = function() {
  if (Folder.prototype._getFiles) {
    Folder.prototype.getFiles = Folder.prototype._getFiles; // restore the original getFiles
    delete Folder.protoype._getFiles;                       // delete our adaptor
  }
}

xbytor

Folder.getFiles() Bug

Post by xbytor »

BTW, earlier this year you made available XTools in the Adobe forum. I have a bit more time free now I am back from Australia and I'd love to have a look at it again if possible.

I probably do need to get that packaged up again. I keep dropping in new bits and pieces and the docs are no where near up to date and I've got a CVS problem I need to get fixed. But I will try to get a version kicked out sometime later this week.