<commit_before>var type = require("./type");
var event = require("./event");
var render = require("./render");

require("./dom-event");

var store = new WeakMap();
var cachedProps = new WeakMap();

function update(dom, component, root) {
  event.emit(component, "update");
  var vtree = component.render();
  render.render(root, vtree);
  event.emit(component, "updated");
}

function emitEvent(dom, component, type, detail) {
  var event = new CustomEvent(type, {
    detail: detail
  });
  dom.dispatchEvent(event);
}

function castType(value, propType) {
  if(propType === type.boolean) {
    return value !== null;
  } else {
    return type.cast(value, propType);
  }
}

function wrapMethod(method) {
  return function() {
    var state = store.get(this);
    return method.apply(state.component, arguments);
  };
}

function register(name, options, componentClass) {
  if(!componentClass) {
    componentClass = options;
    options = undefined;
  }
  options = options || {};
  var propTypes = componentClass.prototype.propTypes;
  var propNames = Object.keys(propTypes);
  var prototype = Object.assign(Object.create(HTMLElement.prototype), {
    createdCallback: function() {
      var props = {};
      propNames.forEach(function(name) {
        var value = this.getAttribute(name);
        if(name !== null) {
          props[name] = castType(value, propTypes[name]);
        }
      }, this);
      var component = new componentClass(props);
      var root = this.createShadowRoot();
      event.on(component, "upstream:update", update.bind(null, this, component, root));
      event.on(component, "upstream:emit-event", emitEvent.bind(null, this, component));
      event.emit(component, "create");
      store.set(this, {
        component: component,
        root: root
      });
    },
    attachedCallback: function() {
      var state = store.get(this);
      event.emit(state.component, "mount", state.root);
    },
    detachedCallback: function() {
      var state = store.get(this);
      event.emit(state.component, "unmount");
    },
    attributeChangedCallback: function(name, previous, value) {
      if(!propTypes[name]) {
        return;
      }
      var state = store.get(this);
      var oldProps = cachedProps.get(this) || {};
      var props = Object.assign({}, oldProps);
      if(value === null) {
        delete props[name];
      } else {
        props[name] = castType(value, propTypes[name]);
      }
      cachedProps.set(this, props);
      state.component.replaceProps(props);
    }
  });
  for(var key in componentClass.prototype.dom) {
    if(componentClass.prototype.dom.hasOwnProperty(key)) {
      var value = componentClass.prototype.dom[key];
      if(typeof value == "function") {
        prototype[key] = wrapMethod(value);
      } else {
        prototype[key] = value;
      }
    }
  }
  document.registerElement(name, {
    prototype: prototype,
    extends: options.extends
  });
}

module.exports = register;
<commit_msg>support getter / setter for element prototype<commit_after>var type = require("./type");
var event = require("./event");
var render = require("./render");

require("./dom-event");

var store = new WeakMap();
var cachedProps = new WeakMap();

function update(dom, component, root) {
  event.emit(component, "update");
  var vtree = component.render();
  render.render(root, vtree);
  event.emit(component, "updated");
}

function emitEvent(dom, component, type, detail) {
  var event = new CustomEvent(type, {
    detail: detail
  });
  dom.dispatchEvent(event);
}

function castType(value, propType) {
  if(propType === type.boolean) {
    return value !== null;
  } else {
    return type.cast(value, propType);
  }
}

function wrapMethod(method) {
  if(!method) {
    return null;
  }
  return function() {
    var state = store.get(this);
    return method.apply(state.component, arguments);
  };
}

function register(name, options, componentClass) {
  if(!componentClass) {
    componentClass = options;
    options = undefined;
  }
  options = options || {};
  var propTypes = componentClass.prototype.propTypes;
  var propNames = Object.keys(propTypes);
  var prototype = Object.assign(Object.create(HTMLElement.prototype), {
    createdCallback: function() {
      var props = {};
      propNames.forEach(function(name) {
        var value = this.getAttribute(name);
        if(name !== null) {
          props[name] = castType(value, propTypes[name]);
        }
      }, this);
      var component = new componentClass(props);
      var root = this.createShadowRoot();
      event.on(component, "upstream:update", update.bind(null, this, component, root));
      event.on(component, "upstream:emit-event", emitEvent.bind(null, this, component));
      event.emit(component, "create");
      store.set(this, {
        component: component,
        root: root
      });
    },
    attachedCallback: function() {
      var state = store.get(this);
      event.emit(state.component, "mount", state.root);
    },
    detachedCallback: function() {
      var state = store.get(this);
      event.emit(state.component, "unmount");
    },
    attributeChangedCallback: function(name, previous, value) {
      if(!propTypes[name]) {
        return;
      }
      var state = store.get(this);
      var oldProps = cachedProps.get(this) || {};
      var props = Object.assign({}, oldProps);
      if(value === null) {
        delete props[name];
      } else {
        props[name] = castType(value, propTypes[name]);
      }
      cachedProps.set(this, props);
      state.component.replaceProps(props);
    }
  });
  for(var key in componentClass.prototype.dom) {
    if(componentClass.prototype.dom.hasOwnProperty(key)) {
      var descriptor = Object.getOwnPropertyDescriptor(componentClass.prototype.dom, key);
      if("value" in descriptor) {
        var value = descriptor.value;
        if(typeof value == "function") {
          value = wrapMethod(value);
        }
        Object.defineProperty(prototype, key, {
          configurable: true,
          enumerable: true,
          writable: true,
          value: value
        });
      } else {
        Object.defineProperty(prototype, key, {
          configurable: true,
          enumerable: true,
          writable: true,
          get: wrapMethod(descriptor.get),
          set: wrapMethod(descriptor.set)
        });
      }
    }
  }
  document.registerElement(name, {
    prototype: prototype,
    extends: options.extends
  });
}

module.exports = register;

{'fraction_non_alphanumeric': 0.14202274823240085, 'fraction_numerical': 0.0, 'mean_word_length': 2.938861985472155, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1405657', 'n_tokens_mistral': 1905, 'n_tokens_neox': 1911, 'n_words': 413}