
/**
 * UserJS shim
 * http://www.opera.com/docs/userjs/specs
 */

EventTarget.mixin( Opera.prototype );

Opera.prototype.defineMagicVariable = function(name, getter, setter) {

  if((!getter || Object.prototype.toString.call(getter) !== "[object Function]") || 
        (!setter || Object.prototype.toString.call(setter) !== "[object Function]")) {
    return;
  }
  
  var magicScriptEl = document.createElement('script');
  magicScriptEl.setAttribute('type', 'text/javascript');

  if (getter && Object.prototype.toString.call(getter) === "[object Function]") {
    magicScriptEl.textContent += "window.__defineGetter__('" + name + "', " + getter.toString() + ");\n";
  }
  
  if (setter && Object.prototype.toString.call(setter) === "[object Function]") {
    magicScriptEl.textContent += "window.__defineSetter__('" + name + "', " + setter.toString() + ");\n";
  }
  
  document.getElementsByTagName('head')[0].appendChild( magicScriptEl );
  document.getElementsByTagName('head')[0].removeChild( magicScriptEl );
  
};

Opera.prototype.defineMagicFunction = function(name, implementation) {
  
  if(!implementation || Object.prototype.toString.call(implementation) !== "[object Function]") {
    return;
  }
  
  var magicScriptEl = document.createElement('script');
  magicScriptEl.setAttribute('type', 'text/javascript');
  
  magicScriptEl.textContent = "var " + name + " = " + implementation.toString() + ";";

  document.getElementsByTagName('head')[0].appendChild( magicScriptEl );
  document.getElementsByTagName('head')[0].removeChild( magicScriptEl );

};

Opera.prototype.addEventListener = function(name, fn, useCapture) {
  // TODO Implement http://www.opera.com/docs/userjs/specs/#evlistener
  // ... this.on(name, function)
};

Opera.prototype.removeEventListener = function(name, fn, useCapture) {
  // TODO Implement http://www.opera.com/docs/userjs/specs/#evlistener
  // ... this.off(name, function)
};

// Same backend implementation as widget.preferences
Opera.prototype.__defineGetter__('scriptStorage', function() {
  return widget.preferences;
});

Opera.prototype.setOverrideHistoryNavigationMode = function(mode) {
  // NOT IMPLEMENTED
};

Opera.prototype.__defineGetter__('getOverrideHistoryNavigationMode', function() {
  return "automatic"; // default
});

@@ -174,25 +174,165 @@
 ) %7B%0A
-%0A
   if(
-(!
+ 
 getter 
-%7C%7C
+=== undefined %7C%7C setter === undefined )%7B%0A    return;%0A  %7D%0A  var allowedStringifications = %7B%22%5Bobject Function%5D%22:1, %22%5Bobject Null%5D%22:1%7D;%0A  if( ! ( (
  Obj
@@ -371,35 +371,40 @@
 er) 
-!== %22%5Bobject Function%5D%22) %7C%7C
+in allowedStringifications ) && 
  %0A  
@@ -414,18 +414,8 @@
    (
-!setter %7C%7C
  Obj
@@ -450,39 +450,43 @@
 setter) 
-!== %22%5Bobject Func
+in allowedStringifica
 tion
-%5D%22
+s 
 )) %7B%0A   

align with the way the old implementations handle undefined and null passed to defineMagicVariable (silent fail on undefined, accept null)