|  | @@ -42,7 +42,9 @@ var _ = require('lodash');
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  var grpc = require('bindings')('grpc.node');
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -var common = require('./common.js');
 | 
	
		
			
				|  |  | +var common = require('./common');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +var Metadata = require('./metadata');
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  var EventEmitter = require('events').EventEmitter;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -254,8 +256,7 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |     *     serialize
 | 
	
		
			
				|  |  |     * @param {function(?Error, value=)} callback The callback to for when the
 | 
	
		
			
				|  |  |     *     response is received
 | 
	
		
			
				|  |  | -   * @param {array=} metadata Array of metadata key/value pairs to add to the
 | 
	
		
			
				|  |  | -   *     call
 | 
	
		
			
				|  |  | +   * @param {Metadata=} metadata Metadata to add to the call
 | 
	
		
			
				|  |  |     * @param {Object=} options Options map
 | 
	
		
			
				|  |  |     * @return {EventEmitter} An event emitter for stream related events
 | 
	
		
			
				|  |  |     */
 | 
	
	
		
			
				|  | @@ -264,7 +265,9 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |      var emitter = new EventEmitter();
 | 
	
		
			
				|  |  |      var call = getCall(this.channel, method, options);
 | 
	
		
			
				|  |  |      if (metadata === null || metadata === undefined) {
 | 
	
		
			
				|  |  | -      metadata = {};
 | 
	
		
			
				|  |  | +      metadata = new Metadata();
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      metadata = metadata.clone();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      emitter.cancel = function cancel() {
 | 
	
		
			
				|  |  |        call.cancel();
 | 
	
	
		
			
				|  | @@ -283,13 +286,16 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |        if (options) {
 | 
	
		
			
				|  |  |          message.grpcWriteFlags = options.flags;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      client_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
 | 
	
		
			
				|  |  | +      client_batch[grpc.opType.SEND_INITIAL_METADATA] =
 | 
	
		
			
				|  |  | +          metadata._getCoreRepresentation();
 | 
	
		
			
				|  |  |        client_batch[grpc.opType.SEND_MESSAGE] = message;
 | 
	
		
			
				|  |  |        client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true;
 | 
	
		
			
				|  |  |        client_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
 | 
	
		
			
				|  |  |        client_batch[grpc.opType.RECV_MESSAGE] = true;
 | 
	
		
			
				|  |  |        client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
 | 
	
		
			
				|  |  |        call.startBatch(client_batch, function(err, response) {
 | 
	
		
			
				|  |  | +        response.status.metadata = Metadata._fromCoreRepresentation(
 | 
	
		
			
				|  |  | +              response.status.metadata);
 | 
	
		
			
				|  |  |          emitter.emit('status', response.status);
 | 
	
		
			
				|  |  |          if (response.status.code !== grpc.status.OK) {
 | 
	
		
			
				|  |  |            var error = new Error(response.status.details);
 | 
	
	
		
			
				|  | @@ -304,7 +310,8 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |              return;
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        emitter.emit('metadata', response.metadata);
 | 
	
		
			
				|  |  | +        emitter.emit('metadata', Metadata._fromCoreRepresentation(
 | 
	
		
			
				|  |  | +            response.metadata));
 | 
	
		
			
				|  |  |          callback(null, deserialize(response.read));
 | 
	
		
			
				|  |  |        });
 | 
	
		
			
				|  |  |      });
 | 
	
	
		
			
				|  | @@ -328,7 +335,7 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |     * @this {Client} Client object. Must have a channel member.
 | 
	
		
			
				|  |  |     * @param {function(?Error, value=)} callback The callback to for when the
 | 
	
		
			
				|  |  |     *     response is received
 | 
	
		
			
				|  |  | -   * @param {array=} metadata Array of metadata key/value pairs to add to the
 | 
	
		
			
				|  |  | +   * @param {Metadata=} metadata Array of metadata key/value pairs to add to the
 | 
	
		
			
				|  |  |     *     call
 | 
	
		
			
				|  |  |     * @param {Object=} options Options map
 | 
	
		
			
				|  |  |     * @return {EventEmitter} An event emitter for stream related events
 | 
	
	
		
			
				|  | @@ -337,7 +344,9 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |      /* jshint validthis: true */
 | 
	
		
			
				|  |  |      var call = getCall(this.channel, method, options);
 | 
	
		
			
				|  |  |      if (metadata === null || metadata === undefined) {
 | 
	
		
			
				|  |  | -      metadata = {};
 | 
	
		
			
				|  |  | +      metadata = new Metadata();
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      metadata = metadata.clone();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      var stream = new ClientWritableStream(call, serialize);
 | 
	
		
			
				|  |  |      this.updateMetadata(this.auth_uri, metadata, function(error, metadata) {
 | 
	
	
		
			
				|  | @@ -347,7 +356,8 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |          return;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        var metadata_batch = {};
 | 
	
		
			
				|  |  | -      metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
 | 
	
		
			
				|  |  | +      metadata_batch[grpc.opType.SEND_INITIAL_METADATA] =
 | 
	
		
			
				|  |  | +          metadata._getCoreRepresentation();
 | 
	
		
			
				|  |  |        metadata_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
 | 
	
		
			
				|  |  |        call.startBatch(metadata_batch, function(err, response) {
 | 
	
		
			
				|  |  |          if (err) {
 | 
	
	
		
			
				|  | @@ -355,12 +365,15 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |            // in the other batch.
 | 
	
		
			
				|  |  |            return;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        stream.emit('metadata', response.metadata);
 | 
	
		
			
				|  |  | +        stream.emit('metadata', Metadata._fromCoreRepresentation(
 | 
	
		
			
				|  |  | +            response.metadata));
 | 
	
		
			
				|  |  |        });
 | 
	
		
			
				|  |  |        var client_batch = {};
 | 
	
		
			
				|  |  |        client_batch[grpc.opType.RECV_MESSAGE] = true;
 | 
	
		
			
				|  |  |        client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
 | 
	
		
			
				|  |  |        call.startBatch(client_batch, function(err, response) {
 | 
	
		
			
				|  |  | +        response.status.metadata = Metadata._fromCoreRepresentation(
 | 
	
		
			
				|  |  | +              response.status.metadata);
 | 
	
		
			
				|  |  |          stream.emit('status', response.status);
 | 
	
		
			
				|  |  |          if (response.status.code !== grpc.status.OK) {
 | 
	
		
			
				|  |  |            var error = new Error(response.status.details);
 | 
	
	
		
			
				|  | @@ -398,7 +411,7 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |     * @this {SurfaceClient} Client object. Must have a channel member.
 | 
	
		
			
				|  |  |     * @param {*} argument The argument to the call. Should be serializable with
 | 
	
		
			
				|  |  |     *     serialize
 | 
	
		
			
				|  |  | -   * @param {array=} metadata Array of metadata key/value pairs to add to the
 | 
	
		
			
				|  |  | +   * @param {Metadata=} metadata Array of metadata key/value pairs to add to the
 | 
	
		
			
				|  |  |     *     call
 | 
	
		
			
				|  |  |     * @param {Object} options Options map
 | 
	
		
			
				|  |  |     * @return {EventEmitter} An event emitter for stream related events
 | 
	
	
		
			
				|  | @@ -407,7 +420,9 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |      /* jshint validthis: true */
 | 
	
		
			
				|  |  |      var call = getCall(this.channel, method, options);
 | 
	
		
			
				|  |  |      if (metadata === null || metadata === undefined) {
 | 
	
		
			
				|  |  | -      metadata = {};
 | 
	
		
			
				|  |  | +      metadata = new Metadata();
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      metadata = metadata.clone();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      var stream = new ClientReadableStream(call, deserialize);
 | 
	
		
			
				|  |  |      this.updateMetadata(this.auth_uri, metadata, function(error, metadata) {
 | 
	
	
		
			
				|  | @@ -421,7 +436,8 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |        if (options) {
 | 
	
		
			
				|  |  |          message.grpcWriteFlags = options.flags;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
 | 
	
		
			
				|  |  | +      start_batch[grpc.opType.SEND_INITIAL_METADATA] =
 | 
	
		
			
				|  |  | +          metadata._getCoreRepresentation();
 | 
	
		
			
				|  |  |        start_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
 | 
	
		
			
				|  |  |        start_batch[grpc.opType.SEND_MESSAGE] = message;
 | 
	
		
			
				|  |  |        start_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true;
 | 
	
	
		
			
				|  | @@ -431,11 +447,14 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |            // in the other batch.
 | 
	
		
			
				|  |  |            return;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        stream.emit('metadata', response.metadata);
 | 
	
		
			
				|  |  | +        stream.emit('metadata', Metadata._fromCoreRepresentation(
 | 
	
		
			
				|  |  | +            response.metadata));
 | 
	
		
			
				|  |  |        });
 | 
	
		
			
				|  |  |        var status_batch = {};
 | 
	
		
			
				|  |  |        status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
 | 
	
		
			
				|  |  |        call.startBatch(status_batch, function(err, response) {
 | 
	
		
			
				|  |  | +        response.status.metadata = Metadata._fromCoreRepresentation(
 | 
	
		
			
				|  |  | +              response.status.metadata);
 | 
	
		
			
				|  |  |          stream.emit('status', response.status);
 | 
	
		
			
				|  |  |          if (response.status.code !== grpc.status.OK) {
 | 
	
		
			
				|  |  |            var error = new Error(response.status.details);
 | 
	
	
		
			
				|  | @@ -470,7 +489,7 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  |     * Make a bidirectional stream request with this method on the given channel.
 | 
	
		
			
				|  |  |     * @this {SurfaceClient} Client object. Must have a channel member.
 | 
	
		
			
				|  |  | -   * @param {array=} metadata Array of metadata key/value pairs to add to the
 | 
	
		
			
				|  |  | +   * @param {Metadata=} metadata Array of metadata key/value pairs to add to the
 | 
	
		
			
				|  |  |     *     call
 | 
	
		
			
				|  |  |     * @param {Options} options Options map
 | 
	
		
			
				|  |  |     * @return {EventEmitter} An event emitter for stream related events
 | 
	
	
		
			
				|  | @@ -479,7 +498,9 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |      /* jshint validthis: true */
 | 
	
		
			
				|  |  |      var call = getCall(this.channel, method, options);
 | 
	
		
			
				|  |  |      if (metadata === null || metadata === undefined) {
 | 
	
		
			
				|  |  | -      metadata = {};
 | 
	
		
			
				|  |  | +      metadata = new Metadata();
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      metadata = metadata.clone();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      var stream = new ClientDuplexStream(call, serialize, deserialize);
 | 
	
		
			
				|  |  |      this.updateMetadata(this.auth_uri, metadata, function(error, metadata) {
 | 
	
	
		
			
				|  | @@ -489,7 +510,8 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |          return;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        var start_batch = {};
 | 
	
		
			
				|  |  | -      start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
 | 
	
		
			
				|  |  | +      start_batch[grpc.opType.SEND_INITIAL_METADATA] =
 | 
	
		
			
				|  |  | +          metadata._getCoreRepresentation();
 | 
	
		
			
				|  |  |        start_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
 | 
	
		
			
				|  |  |        call.startBatch(start_batch, function(err, response) {
 | 
	
		
			
				|  |  |          if (err) {
 | 
	
	
		
			
				|  | @@ -497,11 +519,14 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
 | 
	
		
			
				|  |  |            // in the other batch.
 | 
	
		
			
				|  |  |            return;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        stream.emit('metadata', response.metadata);
 | 
	
		
			
				|  |  | +        stream.emit('metadata', Metadata._fromCoreRepresentation(
 | 
	
		
			
				|  |  | +            response.metadata));
 | 
	
		
			
				|  |  |        });
 | 
	
		
			
				|  |  |        var status_batch = {};
 | 
	
		
			
				|  |  |        status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
 | 
	
		
			
				|  |  |        call.startBatch(status_batch, function(err, response) {
 | 
	
		
			
				|  |  | +        response.status.metadata = Metadata._fromCoreRepresentation(
 | 
	
		
			
				|  |  | +              response.status.metadata);
 | 
	
		
			
				|  |  |          stream.emit('status', response.status);
 | 
	
		
			
				|  |  |          if (response.status.code !== grpc.status.OK) {
 | 
	
		
			
				|  |  |            var error = new Error(response.status.details);
 |