If you include a JS script where you extend a prototype of an Array object, like so:

Array.prototype.delete_first = function(obj) {
    var i = this.indexOf(obj);
    if (i >= 0)
        this.splice(i,1);
    return this;
};

It gets called on ajax requests from admin pages, like when you press "add another item" in edit node form.

This is the call stack:

delete_first(obj=undefined)spike.js?m2024q (line 35)
abort(h="ajax_html_ids[]", l=function())jquery.js?v=1.4.4 (line 142)
handleError()jquery.js?v=1.4.4 (line 143)
nodeName(j=[Object { name="title", value="test"}, Object { name="changed", value="1333726326"}, Object { name="form_build_id", value="form-LzyzUKCsToYFt2eB0w-FQAWTojlXCDM_C3s2iPI7KFM"}, 161 more...], s=function(), v=Object { name="ajax_html_ids[]", value=function()})jquery.js?v=1.4.4 (line 34)
abort(a=[Object { name="title", value="test"}, Object { name="changed", value="1333726326"}, Object { name="form_build_id", value="form-LzyzUKCsToYFt2eB0w-FQAWTojlXCDM_C3s2iPI7KFM"}, 161 more...], b=undefined)jquery.js?v=1.4.4 (line 143)
ajaxSubmit(a=Object { url="/system/ajax", type="POST", iframeSrc="about:blank", more...})jquery...?v=2.52 (line 12)
eventResponse(element=input#edit-field-neurocenter-und-add-more.field-add-more-submit Add another item, event=Object { originalEvent=Event mousedown, type="mousedown", timeStamp=1333726901359, more...})ajax.js?v=7.12 (line 251)
to the element event. $(event=Object { originalEvent=Event mousedown, type="mousedown", timeStamp=1333726901359, more...})ajax.js?v=7.12 (line 178)
handle(a=Object { originalEvent=Event mousedown, type="mousedown", timeStamp=1333726901359, more...})jquery.js?v=1.4.4 (line 64)
add()jquery.js?v=1.4.4 (line 58)
CommentFileSizeAuthor
#4 testm.tar_.gz419 bytesakamaus
#2 core-js-filter-for-ajax-1518012-2.patch535 bytesnod_
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

nod_’s picture

Version: 7.12 » 8.x-dev

The problem is with an unfiltered for loop in Drupal.ajax.prototype.success.

nod_’s picture

Status: Active » Needs review
FileSize
535 bytes

Please test to confirm it's solving the bug in your case.

jcisio’s picture

Status: Needs review » Closed (cannot reproduce)

Can't not reproduce on a vanilla Drupal.

akamaus’s picture

Status: Closed (cannot reproduce) » Needs work
FileSize
419 bytes

I'm pretty sure the bug is there. I've just retested on vanilla D7.12 (standard profile). Steps to reproduce:

  1. Install and enable attached module.
  2. Go to admin/structure/types/manage/page/fields/body and set number of values to Unlimited.
  3. Go to node/add/page and press 'Add another item', you would get a javascript alert message saying "An error occurred while attempting to process /system/ajax: this.indexOf is not a function".
nod_’s picture

Version: 8.x-dev » 7.x-dev
Component: ajax system » javascript

Ok I can reproduce, that is not where I expected the problem would be. It happens before the ajax call so it's an unfiltered for in the form code somewhere. Don't have time to dig deeper just yet. Anyway it's confirmed, we can do something about it now :)

Also this is a D7 only issue, D8 JS has been much more cleaned up and this bug doesn't happen. Also it's in my backyard, not the ajax system.

The best way to correct this bug would be to review/reroll the patch #1428524-22: Replace all $.each() with filtered for loop :)

nod_’s picture

Status: Needs work » Closed (duplicate)

Actuall, closing this one since the other patch will fix this bug.

hngu_shareaholic’s picture

Hi there, are there any plans to apply this patch to Drupal 7 code base itself? I am writing a module that would uses a JS library which loads things into Array.prototype. Currently, the module will cause errors in D7.

nod_’s picture

Feel free to reopen and have a D7 patch. Happy to review.

hngu_shareaholic’s picture

Before I do that, I am hoping to get some thoughts about what I found.

First of all, I have a module which inserts a JS library that adds additional functions to Array's prototype property.

When a user has modules that uses AJAX or AJAX form submit from Drupal's default install, it would throw an error because the array prototype functions are being called. I traced it to jquery.form.js in the following lines:

	var n,v,a = this.formToArray(options.semantic);
	if (options.data) {
		options.extraData = options.data;
		for (n in options.data) {
			if(options.data[n] instanceof Array) {
				for (var k in options.data[n]) {
					a.push( { name: n, value: options.data[n][k] } );
				}
			}
			else {
				v = options.data[n];
				v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
				a.push( { name: n, value: v } );
			}
		}
	}

The line where it checks if options.data[n] is an instance of Array, it does a for-in on that Array object which adds the prototype functions to variable a. It should avoid iterating the prototype object. Can anyone verify this? I may be looking at an old copy of jquery.form.js or something. I looked at the latest jquery.form.js code and it does not have this issue.

bumpshoveit’s picture

flag