Random Unrelated Exceptions thrown in WebGL Build (unity 2018)

I’m getting a lot of strange exceptions from my WebGL build. The exceptions do not turn up in the editor at all. Plus the exceptions being thrown don’t seem to be at all related to what my code is doing. In addition, the exceptions seem to change from build to build even when unrelated and small code changes are made (such as adding or removing a Debug.Log()).

For example when I check the javascript console in chrome/Firefox, once I got:
“MethodAccessException: Attempt to access method”.
Removing or adding a Debug.Log and rebuilding sometimes then switches it to:
“ArgumentException: Name has invalid chars at System.IO.FileStream…ctor”
But other code changes also cause it to switch and there seems to be no rhyme or reason why.
I also got “AbandonedMutexException” a few times and a few others that appeared to be to do with threading even though there is no threading in my code.

I narrowed down (using full exception support with stack trace and debug logs) which line was causing the problem and it was simply the construction of a class. I thought it might be because the class implements an interface with a covariant generic type but then I contructed that class in another context and execution didn’t stop there.

This all seems very strange and obscure. I have copied the offending class below. I guess I’d like to know if anyone else has had similar issues and if they managed to resolve it or if they know what would cause this.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

namespace JY.Collections
{
    /// <summary>
    /// Only allows the retrieval of items by index
    /// </summary>
    /// <typeparam name="TSuper">the type</typeparam>
    public class DelegateReadOnlyList<T,U> : IReadOnlyList<T>
    {

        private class Enumerator : IEnumerator<T>
        {
            private DelegateReadOnlyList<T,U> list;
            private int internalIdx;

            public Enumerator(DelegateReadOnlyList<T,U> list)
            {
                this.list = list;
                Reset();
            }

            public T Current
            {
                get
                {
                    return list[internalIdx];
                }
            }

            object IEnumerator.Current
            {
                get
                {
                    return list[internalIdx];
                }
            }

            public void Dispose()
            {
                //nothing to do here
            }

            public bool MoveNext()
            {
                internalIdx++;
                return internalIdx < list.Count;
            }

            public void Reset()
            {
                internalIdx = -1;
            }
        }
        /// <summary>
        /// The type of delegate that is called by this listener
        /// </summary>
        /// <param name="input">the input parameter</param>
        public delegate T IndexDelegate(int idx);

        /// <summary>
        /// The internal list to wrap
        /// </summary>
        private IReadOnlyList<U> internalCollection;
        private IndexDelegate del;

        /// <summary>
        /// Constructs the collection
        /// </summary>
        /// <param name="internalList">The internal list</param>
        public DelegateReadOnlyList(IReadOnlyList<U> internalArray, IndexDelegate del)
        {
            this.internalCollection = internalArray;
            this.del = del;
        }

        public T this[int index]
        {
            get
            {
                return del(index);
            }
        }

        /// <summary>
        /// The count
        /// </summary>
        public int Count
        {
            get
            {
                return internalCollection.Count;
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new Enumerator(this);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new Enumerator(this);
        }
    }
}

So in the end the strangest thing mostly fixed the issue. I just randomly changed the class a little and WebGL builds started working again. I removed a generic argument and added a delegate, the adjustment can be seen below. However it does not make sense that this fixed the issue because the code worked and compiled in other platforms just. Perhaps there is some strange bug which means that you cannot have multiple generic arguments if implementing from a class with only one with the WebGL target. Of course none of this explains the completely random exceptions I was getting. But I thought I would post what I did anyway in case anyone else comes across this problem.

Note: I was using WebAssembly, targetting .NET 4x, with explicit exceptions only in the WebGL build settings. The builds did not work in Chrome and didn’t work at all if there was no exception support.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

namespace JY.Collections
{
    /// <summary>
    /// Only allows the retrieval of items by index
    /// </summary>
    /// <typeparam name="TSuper">the type</typeparam>
    public class DelegateReadOnlyList<T> : IReadOnlyList<T>
    {

        private class Enumerator : IEnumerator<T>
        {
            private DelegateReadOnlyList<T> list;
            private int internalIdx;

            public Enumerator(DelegateReadOnlyList<T> list)
            {
                this.list = list;
                Reset();
            }

            public T Current
            {
                get
                {
                    return list[internalIdx];
                }
            }

            object IEnumerator.Current
            {
                get
                {
                    return list[internalIdx];
                }
            }

            public void Dispose()
            {
                //nothing to do here
            }

            public bool MoveNext()
            {
                internalIdx++;
                return internalIdx < list.Count;
            }

            public void Reset()
            {
                internalIdx = -1;
            }
        }
        /// <summary>
        /// The type of delegate that is called by this listener
        /// </summary>
        /// <param name="input">the input parameter</param>
        public delegate T IndexDelegate(int idx);
        /// <summary>
        /// The type of delegate that is called by this listener
        /// </summary>
        /// <param name="input">the input parameter</param>
        public delegate int CountDelegate();

        /// <summary>
        /// The internal list to wrap
        /// </summary>
        private IndexDelegate del;

        /// <summary>
        /// The internal list to wrap
        /// </summary>
        private CountDelegate countDel;

        /// <summary>
        /// Constructs the collection
        /// </summary>
        /// <param name="internalList">The internal list</param>
        public DelegateReadOnlyList(CountDelegate countDel, IndexDelegate del)
        {
            this.del = del;
            this.countDel = countDel;
        }

        public T this[int index]
        {
            get
            {
                return del(index);
            }
        }

        /// <summary>
        /// The count
        /// </summary>
        public int Count
        {
            get
            {
                return countDel();
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new Enumerator(this);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new Enumerator(this);
        }
    }
}