docs: function (def) {
                  var classpath = def.$classpath;
                  // Initialize the prototype
                  var proto; // prototype being created
                  var superInterface = null;
                  if (def.$extends) {
                      // the prototype must be created from the super interface
                      superInterface = Aria.getClassRef(def.$extends);
                      if (!superInterface) {
                          this.$logError(this.BASE_INTERFACE_UNDEFINED, [classpath, def.$extends]);
                          throw new Error(this.BASE_INTERFACE_UNDEFINED);
                      }
                      var parentCstr = superInterface ? superInterface.interfaceDefinition : null;
                      parentCstr = parentCstr ? parentCstr.$noargConstructor : null;
                      if (!parentCstr) {
                          this.$logError(this.WRONG_BASE_INTERFACE, [classpath, def.$extends]);
                          throw new Error(this.WRONG_BASE_INTERFACE);
                      }
                      proto = new parentCstr();
                      proto.$interfaces = __copyMap(superInterface.prototype.$interfaces);
                  } else {
                      proto = new __superInterfaceConstructor();
                      proto.$interfaces = {};
                  }
                  proto.$classpath = classpath; // classpath of the interface
                  // Look into the members of the interface, and divide them into functions or properties
                  var itf = def.$interface;
                  var methods = []; // builds the string containing the methods of the interface
                  var initProperties = []; // builds the string to initialize properties of the interface (objects and
                  // arrays)
                  var deleteProperties = []; // builds the string to delete properties of the interface (in $destructor)
                  for (var member in itf) {
                      if (itf.hasOwnProperty(member)) {
                          if (!Aria.checkJsVarName(member) || __superInterfacePrototype[member]) {
                              this.$logError(this.INVALID_INTERFACE_MEMBER, [classpath, member]);
                              // remove and ignore that member:
                              itf[member] = null;
                              delete itf[member];
                              continue;
                          }
                          var memberValue = __normalizeMember.call(this, itf[member], classpath, member);
                          itf[member] = memberValue;
                          if (memberValue != null) {
                              if (memberValue.$type == "Function") {
                                  var asyncParam = memberValue.$callbackParam;
                                  if (asyncParam == null) {
                                      asyncParam = "null";
                                  }
                                  methods.push("p.", member, "=function(){\nreturn i.get(this.__$me).$call('", classpath, "','", member, "',arguments,", asyncParam, ");\n}\n");
                              } else if (memberValue.$type == "Interface") {
                                  initProperties.push("this.", member, "=obj.", member, "?obj.", member, ".$interface('", memberValue.$classpath, "'):null;\n");
                                  deleteProperties.push("this.", member, "=null;\n");
                              } else if (memberValue.$type == "Object") {
                                  initProperties.push("this.", member, "=obj.", member, ";\n");
                                  deleteProperties.push("this.", member, "=null;\n");
                              }
                          } else {
                              this.$logError(this.INVALID_INTERFACE_MEMBER_DEF, [classpath, member]);
                              delete itf[member];
                          }
                      }
                  }
                  // management of events
                  // events in the prototype of the interface
                  proto.$events = {};
                  var parentEvents = false;
                  if (superInterface) {
                      parentEvents = __mergeEvents(proto.$events, superInterface.prototype.$events, classpath);
                  } else {
                      methods.push("p.$interface=function(a){\nreturn aria.core.Interfaces.getInterface(i.get(this.__$me),a,this);\n};\n");
                  }
                  if (__mergeEvents(proto.$events, def.$events, classpath) && !parentEvents) {
                      // The parent interface has no event but this interface has events!
                      // We have to add special wrappers for event handling
                      methods.push("p.$addListeners=function(a){\nreturn i.get(this.__$me).$addListeners(a,this);\n};\n");
                      methods.push("p.$onOnce=function(a){\nreturn i.get(this.__$me).$onOnce(a,this);\n};\n");
                      methods.push("p.$removeListeners=function(a){\nreturn i.get(this.__$me).$removeListeners(a,this);\n};\n");
                      methods.push("p.$unregisterListeners=function(a){\nreturn i.get(this.__$me).$unregisterListeners(a,this);\n};\n");
                      methods.push("p.$on=p.$addListeners;\n");
                  }
                  methods.push("p.$destructor=function(){\n", deleteProperties.join(''), "if(this.__$me){\ni['delete'](this.__$me);\n}\nthis.__$me=null;\n", superInterface
                          ? "e.prototype.$destructor.call(this);\n" /* call super interface at the end of the destructor */
                          : "", "};\n");
                  var srcContent = [];
                  var evalContext = {
                      i : new __weakMap(),
                      p : proto, // prototype
                      c : null, // constructor (will be set by the evaluated code)
                      e : superInterface
                  };
                  Aria.nspace(classpath, true);
                  srcContent.push("var evalContext=arguments[2];\nvar i=evalContext.i;\nvar p=evalContext.p;\nvar e=evalContext.e;\nevalContext.c=function(obj){\n", (superInterface
                          ? 'e.call(this,obj);\n'
                          : ''), 'this.__$me=this.__$me||this;\ni.set(this.__$me,obj);\n', initProperties.join(''), '};\n', methods.join(''), 'Aria.$global.', classpath, '=evalContext.c;\n', 'p=null;\nevalContext=null;\n');
                  srcContent = srcContent.join('');
  
                  // Get original sourceURL of the interface
                  var interfaceSrcURL = downloadMgr.resolveURL( Aria.getLogicalPath(classpath, ".js"), true );
                  // Remove extension and add wrapper extension
                  var indexOfExtension = interfaceSrcURL.lastIndexOf(".");
                  var srcURL = interfaceSrcURL.substring(0,indexOfExtension) + "-wrapper.js";
                  // Generate the interface wrapper
                  Aria["eval"](srcContent, srcURL, evalContext);
                  var constructor = evalContext.c;
                  proto.$interfaces[classpath] = constructor;
                  constructor.prototype = proto;
                  constructor.interfaceDefinition = def;
                  constructor.superInterface = superInterface;
                  def.$noargConstructor = new Function();
                  def.$noargConstructor.prototype = proto;
                  Aria.$classes.push(constructor);
                  return constructor;
              }