{{ var className = "Nan" + it.name; }}

{{#def.idlType}}
{{#def.enum}}
{{#def.impl}}
{{#def.interface}}
{{#def.dictionary}}
{{#def.returnType}}
{{#def.buildValidEnumValuesList}}
{{#def.extractV8Value}}
{{#def.array}}
{{#def.members}}

{{~ getAllPropertyMembers(it) :p:i }}

{{
  var str = getToLocalCheckedString(p.idlType, it.refTypeMap);
  var isStaticProperty = (p.static === true);
  var functionCallPrefix = 'myself->impl_->';
  if ( isStaticProperty ) {
    functionCallPrefix = it.name + '::';
  }
}}

NAN_GETTER({{=className}}::{{=p.name}}Getter) {
{{ var myself = isStaticProperty ? '' : 'myself->'; }}

{{? isStaticProperty }}
{{??}}
  auto myself = ObjectWrap::Unwrap<{{=className}}>(info.Holder());
{{?}}

  auto impl_val = {{=functionCallPrefix}}get_{{=p.name}}();

{{
  var enumCheck = isEnumType(p.idlType, it.refTypeMap);
  var enumDef = getEnumDef(p.idlType, it.refTypeMap);
  var enumName = enumDef.name;
}}

{{? enumCheck }}
  // Valid enum values for parameter info{{=j}}, original IDL type: {{=enumName}}
  const char* VALID_ENUM_{{=(enumName.toUpperCase())}}_INFO[] = { {{=buildValidEnumValuesList(enumDef)}} };
  if (IsEnumValueValid(impl_val, VALID_ENUM_{{=(enumName.toUpperCase())}}_INFO)) {
    info.GetReturnValue().Set(Nan::New(impl_val){{=str}});
  } else {
    // TODO: modify nanCxxImplProperty.def to handle this case
  }


{{?? isInterface(p.idlType, it.refTypeMap) && !isArray(p.idlType)}}
{{ var retType = p.idlType.idlType; }}
  if (! {{=myself}}{{=p.name}}_) {
    {{=myself}}{{=p.name}}_.reset(new Nan::Persistent<v8::Object>(Nan{{=retType}}::NewInstance()));
  }
  v8::Local<v8::Object> obj = Nan::New(*{{=myself}}{{=p.name}}_);
  auto obj_ptr = ObjectWrap::Unwrap<Nan{{=retType}}>(obj);
  if (impl_val) {
    auto old_ptr = obj_ptr->Get{{=retType}}Impl();
    if ( old_ptr != impl_val) {
      delete old_ptr;
    }
    obj_ptr->Borrow{{=retType}}Impl(impl_val);
    info.GetReturnValue().Set(obj);
  } else {
    info.GetReturnValue().Set(Nan::Undefined());
  }
{{?? isDictionary(p.idlType, it.refTypeMap)}}
  info.GetReturnValue().Set(static_cast<v8::Local<v8::Object>>(impl_val));
{{?? isArray(p.idlType) }}
  info.GetReturnValue().Set(static_cast<v8::Local<v8::Array>>(impl_val));
{{?? isTypedArray(p.idlType) }}
  info.GetReturnValue().Set(impl_val.GetTypedArray());
{{?? p.idlType.idlType === 'ArrayBuffer' }}
  if (! {{=myself}}{{=p.name}}_) {
    v8::Local<v8::Object> value;
    if(Nan::NewBuffer(impl_val.data, impl_val.size).ToLocal(&value)) {
      {{=myself}}{{=p.name}}_.reset(new Nan::Persistent<v8::Object>(value));
    }
  }

  if ({{=myself}}{{=p.name}}_) {
    v8::Local<v8::Object> obj = Nan::New(*{{=myself}}{{=p.name}}_);
    info.GetReturnValue().Set(obj);
  } else {
    info.GetReturnValue().Set(Nan::Undefined());
  }
{{?? true}}
  info.GetReturnValue().Set(Nan::New(impl_val){{=str}});
{{?}}

}

{{? ! p.readonly }}
NAN_SETTER({{=className}}::{{=p.name}}Setter) {
{{? !isStaticProperty }}
  auto myself = ObjectWrap::Unwrap<{{=className}}>(info.Holder());
{{?}}
  auto v8_value = {{=extractArgument(p.idlType, it.refTypeMap)}}(value);

{{
  var enumCheck = isEnumType(p.idlType, it.refTypeMap);
  var enumDef = getEnumDef(p.idlType, it.refTypeMap);
  var enumName = enumDef.name;
}}

{{? enumCheck }}
  // Valid enum values for parameter info{{=j}}, original IDL type: {{=enumName}}
  const char* VALID_ENUM_{{=(enumName.toUpperCase())}}_INFO[] = { {{=buildValidEnumValuesList(enumDef)}} };
  if (IsEnumValueValid(v8_value, VALID_ENUM_{{=(enumName.toUpperCase())}}_INFO)) {
    {{=functionCallPrefix}}set_{{=p.name}}(v8_value);
  } else {
    // TODO: modify nanCxxImplProperty.def to handle this case
  }
{{?? isInterface(p.idlType, it.refTypeMap) && !isArray(p.idlType)}}
  // Extract data from the JavaScript object
  // First, convert to impl {{=p.idlType.idlType}} pointer
  auto impl_value = *(ObjectWrap::Unwrap<Nan{{=p.idlType.idlType}}>(v8_value)->{{=generateGetImplMethodName(p.idlType.idlType)}}());
  {{=functionCallPrefix}}set_{{=p.name}}(impl_value);
{{?? true}}
  {{=functionCallPrefix}}set_{{=p.name}}(v8_value);
{{?}}

}
{{?}}

{{~}}
