Commit 51f472fe by Johannes Ewald

Add stats-object

parent d9058348
......@@ -8,7 +8,6 @@
using namespace v8;
using namespace std;
void WorkOnContext(uv_work_t* req) {
sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(req->data);
if (ctx_w->ctx) {
......@@ -20,19 +19,18 @@ void WorkOnContext(uv_work_t* req) {
}
}
char* CreateString(Handle<Value> arg) {
String::AsciiValue str(arg);
char* newStr = new char[str.length() + 1];
strcpy(newStr, *str);
return newStr;
char* CreateString(Local<Value> value) {
size_t count;
return NanCString(value, &count);
}
void extractOptions(_NAN_METHOD_ARGS, void* cptr, sass_context_wrapper* ctx_w, bool isFile) {
void ExtractOptions(Local<Value> optionsValue, void* cptr, sass_context_wrapper* ctx_w, bool isFile) {
int source_comments;
Local<Object> options = Local<Object>::Cast(args[0]);
Local<Object> options = Local<Object>::Cast(optionsValue);
if (ctx_w) {
NanInitPersistent(Object, stats, Local<Object>::Cast(options->Get(NanSymbol("stats"))));
// async (callback) style
Local<Function> callback = Local<Function>::Cast(options->Get(NanSymbol("success")));
Local<Function> errorCallback = Local<Function>::Cast(options->Get(NanSymbol("error")));
......@@ -41,13 +39,14 @@ void extractOptions(_NAN_METHOD_ARGS, void* cptr, sass_context_wrapper* ctx_w, b
} else {
ctx_w->ctx = (sass_context*) cptr;
}
ctx_w->stats = stats;
ctx_w->request.data = ctx_w;
ctx_w->callback = new NanCallback(callback);
ctx_w->errorCallback = new NanCallback(errorCallback);
}
if (isFile) {
sass_file_context *ctx = (sass_file_context*)cptr;
sass_file_context* ctx = (sass_file_context*) cptr;
ctx->input_path = CreateString(options->Get(NanSymbol("file")));
ctx->options.image_path = CreateString(options->Get(NanSymbol("imagePath")));
ctx->options.output_style = options->Get(NanSymbol("style"))->Int32Value();
......@@ -57,7 +56,7 @@ void extractOptions(_NAN_METHOD_ARGS, void* cptr, sass_context_wrapper* ctx_w, b
ctx->source_map_file = CreateString(options->Get(NanSymbol("sourceMap")));
}
} else {
sass_context *ctx = (sass_context*)cptr;
sass_context* ctx = (sass_context*) cptr;
ctx->source_string = CreateString(options->Get(NanSymbol("data")));
ctx->options.image_path = CreateString(options->Get(NanSymbol("imagePath")));
ctx->options.output_style = options->Get(NanSymbol("style"))->Int32Value();
......@@ -66,14 +65,44 @@ void extractOptions(_NAN_METHOD_ARGS, void* cptr, sass_context_wrapper* ctx_w, b
}
}
template<typename Ctx>
void FillStatsObj(Handle<Object> stats, Ctx ctx) {
int i;
Handle<Array> arr;
arr = Array::New(ctx->num_included_files);
for (i = 0; i < ctx->num_included_files; i++) {
arr->Set(i, String::New(ctx->included_files[i]));
}
(*stats)->Set(NanSymbol("includedFiles"), arr);
}
void FillStatsObj(Handle<Object> stats, sass_file_context* ctx) {
Handle<Value> source_map;
FillStatsObj<sass_file_context*>(stats, ctx);
if (ctx->options.source_comments == SASS_SOURCE_COMMENTS_MAP) {
source_map = String::New(ctx->source_map_string);
} else {
source_map = Null();
}
(*stats)->Set(NanSymbol("sourceMap"), source_map);
}
void MakeCallback(uv_work_t* req) {
NanScope();
TryCatch try_catch;
sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(req->data);
Handle<Value> val, err;
const unsigned argc = 2;
int error_status = ctx_w->ctx ? ctx_w->ctx->error_status : ctx_w->fctx->error_status;
if (ctx_w->ctx) {
FillStatsObj(ctx_w->stats, ctx_w->ctx);
} else {
FillStatsObj(ctx_w->stats, ctx_w->fctx);
}
if (error_status == 0) {
// if no error, do callback(null, result)
Handle<Value> source_map;
......@@ -84,28 +113,23 @@ void MakeCallback(uv_work_t* req) {
}
val = ctx_w->ctx ? NanNewLocal(String::New(ctx_w->ctx->output_string)) : NanNewLocal(String::New(ctx_w->fctx->output_string));
Local<Value> argv[argc] = {
Local<Value> argv[] = {
NanNewLocal(val),
NanNewLocal(source_map),
NanNewLocal(source_map)
};
ctx_w->callback->Call(argc, argv);
ctx_w->callback->Call(2, argv);
} else {
// if error, do callback(error)
err = ctx_w->ctx ? NanNewLocal(String::New(ctx_w->ctx->error_message)) : NanNewLocal(String::New(ctx_w->fctx->error_message));
Local<Value> argv[argc] = {
Local<Value> argv[] = {
NanNewLocal(err),
NanNewLocal(Integer::New(error_status))
};
ctx_w->errorCallback->Call(argc, argv);
ctx_w->errorCallback->Call(2, argv);
}
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
if (ctx_w->ctx) {
delete ctx_w->ctx->source_string;
} else {
delete ctx_w->fctx->input_path;
}
sass_free_context_wrapper(ctx_w);
}
......@@ -115,7 +139,7 @@ NAN_METHOD(Render) {
sass_context* ctx = sass_new_context();
sass_context_wrapper* ctx_w = sass_new_context_wrapper();
ctx_w->ctx = ctx;
extractOptions(args, ctx, ctx_w, false);
ExtractOptions(args[0], ctx, ctx_w, false);
int status = uv_queue_work(uv_default_loop(), &ctx_w->request, WorkOnContext, (uv_after_work_cb)MakeCallback);
assert(status == 0);
......@@ -125,25 +149,22 @@ NAN_METHOD(Render) {
NAN_METHOD(RenderSync) {
NanScope();
Handle<Object> options = args[0]->ToObject();
sass_context* ctx = sass_new_context();
extractOptions(args, ctx, NULL, false);
ExtractOptions(args[0], ctx, NULL, false);
sass_compile(ctx);
delete ctx->source_string;
ctx->source_string = NULL;
delete ctx->options.include_paths;
ctx->options.include_paths = NULL;
FillStatsObj(options->Get(NanSymbol("stats"))->ToObject(), ctx);
if (ctx->error_status == 0) {
Local<Value> output = NanNewLocal(String::New(ctx->output_string));
sass_free_context(ctx);
free_context(ctx);
NanReturnValue(output);
}
Local<String> error = String::New(ctx->error_message);
sass_free_context(ctx);
free_context(ctx);
NanThrowError(error);
NanReturnUndefined();
}
......@@ -153,7 +174,7 @@ NAN_METHOD(RenderFile) {
sass_file_context* fctx = sass_new_file_context();
sass_context_wrapper* ctx_w = sass_new_context_wrapper();
ctx_w->fctx = fctx;
extractOptions(args, fctx, ctx_w, true);
ExtractOptions(args[0], fctx, ctx_w, true);
int status = uv_queue_work(uv_default_loop(), &ctx_w->request, WorkOnContext, (uv_after_work_cb)MakeCallback);
assert(status == 0);
......@@ -164,24 +185,21 @@ NAN_METHOD(RenderFile) {
NAN_METHOD(RenderFileSync) {
NanScope();
sass_file_context* ctx = sass_new_file_context();
extractOptions(args, ctx, NULL, true);
ExtractOptions(args[0], ctx, NULL, true);
Handle<Object> options = args[0]->ToObject();
sass_compile_file(ctx);
delete ctx->input_path;
ctx->input_path = NULL;
delete ctx->options.include_paths;
ctx->options.include_paths = NULL;
FillStatsObj(options->Get(NanSymbol("stats"))->ToObject(), ctx);
if (ctx->error_status == 0) {
Local<Value> output = NanNewLocal(String::New(ctx->output_string));
sass_free_file_context(ctx);
free_file_context(ctx);
NanReturnValue(output);
}
Local<String> error = String::New(ctx->error_message);
sass_free_file_context(ctx);
Local<String> error = String::New(ctx->error_message);
free_file_context(ctx);
NanThrowError(error);
NanReturnUndefined();
}
......
......@@ -3,14 +3,14 @@ var fs = require('fs');
function requireBinding() {
var v8 = 'v8-' + /[0-9]+\.[0-9]+/.exec(process.versions.v8)[0];
var candidates = [
[__dirname, 'build', 'Release', 'obj.target', 'binding.node'],
[__dirname, 'bin', process.platform + '-' + process.arch + '-' + v8, 'binding.node'],
[__dirname, 'bin', process.platform + '-' + process.arch + '-' + v8, 'binding.node']
];
var candidate;
for (var i = 0, l = candidates.length; i < l; i++) {
var candidate = path.join.apply(path.join, candidates[i]);
candidate = path.join.apply(path.join, candidates[i]);
if (fs.existsSync(candidate)) {
return require(candidate);
......@@ -27,25 +27,31 @@ var SASS_OUTPUT_STYLE = {
expanded: 1,
compact: 2,
compressed: 3
};
};
var SASS_SOURCE_COMMENTS = {
none: 0,
normal: 1,
'default': 1,
map: 2
};
var noop = function () {};
};
var prepareOptions = function (options) {
var success;
var error;
var stats;
var sourceComments;
options = options || {};
success = options.success;
error = options.error;
stats = options.stats || {};
sourceComments = options.source_comments || options.sourceComments;
if (options.sourceMap && !sourceComments) {
sourceComments = 'map';
}
prepareStats(options, stats);
return {
file: options.file || null,
......@@ -55,12 +61,33 @@ var prepareOptions = function (options) {
imagePath: options.image_path || options.imagePath || '',
style: SASS_OUTPUT_STYLE[options.output_style || options.outputStyle] || 0,
comments: SASS_SOURCE_COMMENTS[sourceComments] || 0,
stats: stats,
sourceMap: options.sourceMap,
success: options.success || noop,
error: options.error || noop
success: function onSuccess(css, sourceMap) {
finishStats(stats, sourceMap);
success && success(css, sourceMap);
},
error: function onError(err, errStatus) {
error && error(err, errStatus);
}
};
};
var prepareStats = function (options, stats) {
stats.entry = options.file || 'data';
stats.start = Date.now();
return stats;
};
var finishStats = function (stats, sourceMap) {
stats.end = Date.now();
stats.duration = stats.end - stats.start;
stats.sourceMap = sourceMap;
return stats;
};
var deprecatedRender = function(css, callback, options) {
options = prepareOptions(options);
// providing the deprecated single callback signature
......@@ -68,12 +95,14 @@ var deprecatedRender = function(css, callback, options) {
options.success = function(css) {
callback(null, css);
};
return binding.render(css, options.imagePath, options.success, options.error, options.paths, options.style, options.comments);
options.data = css;
binding.render(options);
};
var deprecatedRenderSync = function(css, options) {
options = prepareOptions(options);
return binding.renderSync(css, options.imagePath, options.paths, options.style, options.comments);
options.data = css;
return binding.renderSync(options);
};
exports.render = function(options) {
......@@ -82,28 +111,21 @@ exports.render = function(options) {
}
options = prepareOptions(options);
if (options.file) {
return binding.renderFile(options.file, options.imagePath, options.success, options.error, options.paths, options.style, options.comments, options.sourceMap);
}
//Assume data is present if file is not. binding/libsass will tell the user otherwise!
return binding.render(options.data, options.imagePath, options.success, options.error, options.paths, options.style);
options.file? binding.renderFile(options) : binding.render(options);
};
exports.renderSync = function(options) {
var output;
if (typeof arguments[0] === 'string') {
return deprecatedRenderSync.apply(this, arguments);
}
options = prepareOptions(options);
output = options.file? binding.renderFileSync(options) : binding.renderSync(options);
finishStats(options.stats);
if (options.file) {
return binding.renderFileSync(options.file, options.imagePath, options.paths, options.style, options.comments);
}
//Assume data is present if file is not. binding/libsass will tell the user otherwise!
return binding.renderSync(options.data, options.imagePath, options.paths, options.style);
return output;
};
/**
......
#include "sass_context_wrapper.h"
#include <nan.h>
#include <cstdlib>
extern "C" {
using namespace std;
sass_context_wrapper* sass_new_context_wrapper()
{
void free_context(sass_context* ctx) {
delete[] ctx->source_string;
delete[] ctx->options.include_paths;
delete[] ctx->options.image_path;
sass_free_context(ctx);
}
void free_file_context(sass_file_context* fctx) {
delete[] fctx->input_path;
delete[] fctx->output_path;
delete[] fctx->options.include_paths;
delete[] fctx->options.image_path;
sass_free_file_context(fctx);
}
sass_context_wrapper* sass_new_context_wrapper() {
return (sass_context_wrapper*) calloc(1, sizeof(sass_context_wrapper));
}
void sass_free_context_wrapper(sass_context_wrapper* ctx_w)
{
if (ctx_w->ctx) sass_free_context(ctx_w->ctx);
if (ctx_w->fctx) sass_free_file_context(ctx_w->fctx);
void sass_free_context_wrapper(sass_context_wrapper* ctx_w) {
if (ctx_w->ctx) {
free_context(ctx_w->ctx);
} else if (ctx_w->fctx) {
free_file_context(ctx_w->fctx);
}
NanDisposePersistent(ctx_w->stats);
delete ctx_w->callback;
delete ctx_w->errorCallback;
......
......@@ -5,9 +5,15 @@
extern "C" {
#endif
using namespace v8;
void free_context(sass_context* ctx);
void free_file_context(sass_file_context* fctx);
struct sass_context_wrapper {
sass_context* ctx;
sass_file_context* fctx;
Persistent<Object> stats;
uv_work_t request;
NanCallback* callback;
NanCallback* errorCallback;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment