Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I made an object wrapper/parameter injector and I hope it will be useful, I made it for a project I am working on but then decided to try polishing it a bit.

The use case is for wrapping objects such that you can inject parameters into their methods by calling the wrapper as a function. I was heavily inspired by AngularJS and their use of parameter injection to almost create a DSL with their framework.

I'm looking for answers to these questions: Is this a well-designed module? Is my code legible? Am I over looking something that might lead to bugs later? Is something like this safe to use?

Answers to questions I didn't ask are also welcome.

I'm including a link to the repo here. The code follows

###
negotiator.js

A small tool for proxying objects behind a wrapper that can inject
parameters into their methods.
###


# Extract parameter names from a function,
# position is given by position this array.
if module
  _ = require('underscore');
else
  _ = window._

utils = {};

utils.parameterNames = (func) ->

  funcArgs = func.toString().split('(')[1].split(')')[0].split(',')

  return (k.trim() for k in funcArgs)


# Inject parameters from a context object into a function.
# Passed parameters are supplied by the 'params' argument.
utils.injectAndApply =(func, parameters, context, target) ->

  signature = utils.parameterNames func
  parameters = [] if _.isEmpty(parameters)

  for position, name of signature
    parameters[position] = context[name] if context[name]?

  parameters.length = signature.length;
  return func.apply target ? {}, parameters


# Constructor for proxy object.
utils.Proxy = (real) ->

  @$real = real
  self = this

  for key, method of real when typeof method is 'function'
    do (method, key) ->
      self[key] = ->
        utils.injectAndApply method, arguments, @$context ? {}, @$real

  return this


# Build a context object from an arguments list.
utils.buildContextFromParams = (func, parameters) ->
  signature = utils.parameterNames func
  context = {}
  for key, value of parameters
    context[signature[key]] = value

  return context


# This is the circular wrapper that returns a version of itself with
# a set context.
utils.innerWrapper = (proxy, templateFunction, parameters) ->
  wrapper = ->
    utils.innerWrapper(proxy,templateFunction,arguments);

  context = utils.buildContextFromParams templateFunction, parameters 
  context.$real = proxy.$real
  context.$wrapper = wrapper
  context.$proxy =  proxy
  context.$context = context;
  utils.injectAndApply templateFunction, parameters, context, proxy
  wrapper.$context = context;

  wrapper.__proto__ = proxy;

  return wrapper

# Returns a function that wraps object.
# not intended to be called as a constructor
utils.makeWrapper = (real, templateFunction) ->
  proxy = new utils.Proxy real

  return utils.innerWrapper proxy, templateFunction, []

negotiator = utils.makeWrapper
negotiator.utils = utils;

if module
  module.exports = negotiator
else
  window.negotiator = negotiator

return
share|improve this question
I don't know if this is useful advice but you could use some common CoffeeScript conventions like implicit returns, and => to bind a function to the current value of this. You also don't need to end lines with semicolons. I highlighted some of these with #CR: in this Gist: gist.github.com/wildlyinaccurate/5021863 – WildlyInaccurate Feb 23 at 23:42

Know someone who can answer? Share a link to this question via email, Google+, Twitter, or Facebook.

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.