Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit e3ca075

Browse files
authored
Merge pull request #2128 from stefanpenner/leaks
Fix Some Leaks
2 parents 0a0f5c6 + f6b0c72 commit e3ca075

22 files changed

+864
-159
lines changed

memory-tests/_measure.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"use strict";
2+
3+
module.exports = function iterateAndMeasure(fn, mod = 1000000) {
4+
let count = 0;
5+
while (true) {
6+
count++;
7+
fn();
8+
if (count % mod === 0) {
9+
console.log(process.memoryUsage().rss / 1000000);
10+
}
11+
}
12+
}

memory-tests/boolean.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use strict';
2+
3+
var types = require('../').types;
4+
var iterateAndMeasure = require('./_measure');
5+
6+
iterateAndMeasure(function() { return types.Boolean(true).getValue(); });

memory-tests/function-bridge.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"use strict";
2+
3+
var sass = require("../");
4+
var iterateAndMeasure = require('./_measure');
5+
6+
iterateAndMeasure(function() {
7+
sass.renderSync({
8+
data: '#{headings()} { color: #08c; }',
9+
functions: {
10+
'headings()': function() {
11+
return new sass.types.String('hi');
12+
}
13+
}
14+
});
15+
}, 10000);

memory-tests/map.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use strict';
2+
3+
var types = require('../').types;
4+
var iterateAndMeasure = require('./_measure');
5+
6+
iterateAndMeasure(function() {
7+
var key = new types.String('the-key');
8+
var value = new types.String('the-value');
9+
10+
var map = new types.Map(1);
11+
12+
map.setKey(0, key);
13+
map.setValue(0, value);
14+
15+
map.getKey(0);
16+
}, 100000);
17+

memory-tests/string.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use strict';
2+
3+
var types = require('../').types;
4+
var iterateAndMeasure = require('./_measure');
5+
6+
iterateAndMeasure(function() { return new types.String('hi'); });

src/binding.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,9 @@ int ExtractOptions(v8::Local<v8::Object> options, void* cptr, sass_context_wrapp
158158
CustomFunctionBridge *bridge = new CustomFunctionBridge(callback, ctx_w->is_sync);
159159
ctx_w->function_bridges.push_back(bridge);
160160

161-
Sass_Function_Entry fn = sass_make_function(create_string(signature), sass_custom_function, bridge);
161+
char* sig = create_string(signature);
162+
Sass_Function_Entry fn = sass_make_function(sig, sass_custom_function, bridge);
163+
free(sig);
162164
sass_function_set_list_entry(fn_list, i, fn);
163165
}
164166

@@ -267,7 +269,7 @@ NAN_METHOD(render) {
267269
struct Sass_Data_Context* dctx = sass_make_data_context(source_string);
268270
sass_context_wrapper* ctx_w = sass_make_context_wrapper();
269271

270-
if (ExtractOptions(options, dctx, ctx_w, false, false) >= 0) {
272+
if (ExtractOptions(options, dctx, ctx_w, false, false) >= 0) {
271273

272274
int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback);
273275

@@ -290,6 +292,7 @@ NAN_METHOD(render_sync) {
290292
}
291293

292294
sass_free_context_wrapper(ctx_w);
295+
293296
info.GetReturnValue().Set(result == 0);
294297
}
295298

src/callback_bridge.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Nan::Persistent<v8::Function> CallbackBridge<T, L>::wrapper_constructor;
5555

5656
template <typename T, typename L>
5757
CallbackBridge<T, L>::CallbackBridge(v8::Local<v8::Function> callback, bool is_sync) : callback(new Nan::Callback(callback)), is_sync(is_sync) {
58-
/*
58+
/*
5959
* This is invoked from the main JavaScript thread.
6060
* V8 context is available.
6161
*/
@@ -89,7 +89,7 @@ template <typename T, typename L>
8989
T CallbackBridge<T, L>::operator()(std::vector<void*> argv) {
9090
// argv.push_back(wrapper);
9191
if (this->is_sync) {
92-
/*
92+
/*
9393
* This is invoked from the main JavaScript thread.
9494
* V8 context is available.
9595
*
@@ -110,7 +110,7 @@ T CallbackBridge<T, L>::operator()(std::vector<void*> argv) {
110110
this->callback->Call(argv_v8.size(), &argv_v8[0])
111111
);
112112
} else {
113-
/*
113+
/*
114114
* This is invoked from the worker thread.
115115
* No V8 context and functions available.
116116
* Just wait for response from asynchronously
@@ -141,7 +141,7 @@ template <typename T, typename L>
141141
void CallbackBridge<T, L>::dispatched_async_uv_callback(uv_async_t *req) {
142142
CallbackBridge* bridge = static_cast<CallbackBridge*>(req->data);
143143

144-
/*
144+
/*
145145
* Function scheduled via uv_async mechanism, therefore
146146
* it is invoked from the main JavaScript thread.
147147
* V8 context is available.
@@ -169,7 +169,7 @@ void CallbackBridge<T, L>::dispatched_async_uv_callback(uv_async_t *req) {
169169
template <typename T, typename L>
170170
NAN_METHOD(CallbackBridge<T COMMA L>::ReturnCallback) {
171171

172-
/*
172+
/*
173173
* Callback function invoked by the user code.
174174
* It is invoked from the main JavaScript thread.
175175
* V8 context is available.

src/custom_function_bridge.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
#include "sass_types/factory.h"
55
#include "sass_types/value.h"
66

7-
Sass_Value* CustomFunctionBridge::post_process_return_value(v8::Local<v8::Value> val) const {
8-
SassTypes::Value *v_;
9-
if ((v_ = SassTypes::Factory::unwrap(val))) {
10-
return v_->get_sass_value();
7+
Sass_Value* CustomFunctionBridge::post_process_return_value(v8::Local<v8::Value> _val) const {
8+
SassTypes::Value *value = SassTypes::Factory::unwrap(_val);
9+
if (value) {
10+
return value->get_sass_value();
1111
} else {
1212
return sass_make_error("A SassValue object was expected.");
1313
}
@@ -17,7 +17,10 @@ std::vector<v8::Local<v8::Value>> CustomFunctionBridge::pre_process_args(std::ve
1717
std::vector<v8::Local<v8::Value>> argv = std::vector<v8::Local<v8::Value>>();
1818

1919
for (void* value : in) {
20-
argv.push_back(SassTypes::Factory::create(static_cast<Sass_Value*>(value))->get_js_object());
20+
Sass_Value* x = static_cast<Sass_Value*>(value);
21+
SassTypes::Value* y = SassTypes::Factory::create(x);
22+
23+
argv.push_back(y->get_js_object());
2124
}
2225

2326
return argv;

src/custom_importer_bridge.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ SassImportList CustomImporterBridge::post_process_return_value(v8::Local<v8::Val
2929
imports[i] = sass_make_import_entry(0, 0, 0);
3030

3131
sass_import_set_error(imports[i], message, -1, -1);
32+
free(message);
3233
}
3334
else {
3435
imports[i] = get_importer_entry(object);
@@ -43,6 +44,7 @@ SassImportList CustomImporterBridge::post_process_return_value(v8::Local<v8::Val
4344
imports[0] = sass_make_import_entry(0, 0, 0);
4445

4546
sass_import_set_error(imports[0], message, -1, -1);
47+
free(message);
4648
}
4749
else if (returned_value->IsObject()) {
4850
imports = sass_make_import_list(1);
@@ -55,12 +57,12 @@ SassImportList CustomImporterBridge::post_process_return_value(v8::Local<v8::Val
5557
Sass_Import* CustomImporterBridge::check_returned_string(Nan::MaybeLocal<v8::Value> value, const char *msg) const
5658
{
5759
v8::Local<v8::Value> checked;
58-
if (value.ToLocal(&checked)) {
60+
if (value.ToLocal(&checked)) {
5961
if (!checked->IsUndefined() && !checked->IsString()) {
6062
goto err;
6163
} else {
6264
return nullptr;
63-
}
65+
}
6466
}
6567
err:
6668
auto entry = sass_make_import_entry(0, 0, 0);

src/sass_types/boolean.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ namespace SassTypes
66
Nan::Persistent<v8::Function> Boolean::constructor;
77
bool Boolean::constructor_locked = false;
88

9-
Boolean::Boolean(bool v) : value(v) {}
9+
Boolean::Boolean(bool _value) {
10+
value = sass_make_boolean(_value);
11+
}
1012

1113
Boolean& Boolean::get_singleton(bool v) {
1214
static Boolean instance_false(false), instance_true(true);
@@ -15,7 +17,7 @@ namespace SassTypes
1517

1618
v8::Local<v8::Function> Boolean::get_constructor() {
1719
Nan::EscapableHandleScope scope;
18-
v8::Local<v8::Function> conslocal;
20+
v8::Local<v8::Function> conslocal;
1921
if (constructor.IsEmpty()) {
2022
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
2123

@@ -42,16 +44,15 @@ namespace SassTypes
4244
return scope.Escape(conslocal);
4345
}
4446

45-
Sass_Value* Boolean::get_sass_value() {
46-
return sass_make_boolean(value);
47-
}
48-
4947
v8::Local<v8::Object> Boolean::get_js_object() {
5048
return Nan::New(this->js_object);
5149
}
5250

53-
NAN_METHOD(Boolean::New) {
51+
v8::Local<v8::Boolean> Boolean::get_js_boolean() {
52+
return sass_boolean_get_value(this->value) ? Nan::True() : Nan::False();
53+
}
5454

55+
NAN_METHOD(Boolean::New) {
5556
if (info.IsConstructCall()) {
5657
if (constructor_locked) {
5758
return Nan::ThrowTypeError("Cannot instantiate SassBoolean");
@@ -67,9 +68,6 @@ namespace SassTypes
6768
}
6869

6970
NAN_METHOD(Boolean::GetValue) {
70-
Boolean *out;
71-
if ((out = static_cast<Boolean*>(Factory::unwrap(info.This())))) {
72-
info.GetReturnValue().Set(Nan::New(out->value));
73-
}
71+
info.GetReturnValue().Set(Boolean::Unwrap<Boolean>(info.This())->get_js_boolean());
7472
}
7573
}

src/sass_types/boolean.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ namespace SassTypes
1212
static Boolean& get_singleton(bool);
1313
static v8::Local<v8::Function> get_constructor();
1414

15-
Sass_Value* get_sass_value();
1615
v8::Local<v8::Object> get_js_object();
1716

1817
static NAN_METHOD(New);
@@ -21,11 +20,11 @@ namespace SassTypes
2120
private:
2221
Boolean(bool);
2322

24-
bool value;
2523
Nan::Persistent<v8::Object> js_object;
2624

2725
static Nan::Persistent<v8::Function> constructor;
2826
static bool constructor_locked;
27+
v8::Local<v8::Boolean> get_js_boolean();
2928
};
3029
}
3130

src/sass_types/color.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,19 @@ namespace SassTypes
6262
}
6363

6464
NAN_METHOD(Color::GetR) {
65-
info.GetReturnValue().Set(sass_color_get_r(unwrap(info.This())->value));
65+
info.GetReturnValue().Set(sass_color_get_r(Color::Unwrap<Color>(info.This())->value));
6666
}
6767

6868
NAN_METHOD(Color::GetG) {
69-
info.GetReturnValue().Set(sass_color_get_g(unwrap(info.This())->value));
69+
info.GetReturnValue().Set(sass_color_get_g(Color::Unwrap<Color>(info.This())->value));
7070
}
7171

7272
NAN_METHOD(Color::GetB) {
73-
info.GetReturnValue().Set(sass_color_get_b(unwrap(info.This())->value));
73+
info.GetReturnValue().Set(sass_color_get_b(Color::Unwrap<Color>(info.This())->value));
7474
}
7575

7676
NAN_METHOD(Color::GetA) {
77-
info.GetReturnValue().Set(sass_color_get_a(unwrap(info.This())->value));
77+
info.GetReturnValue().Set(sass_color_get_a(Color::Unwrap<Color>(info.This())->value));
7878
}
7979

8080
NAN_METHOD(Color::SetR) {
@@ -86,7 +86,7 @@ namespace SassTypes
8686
return Nan::ThrowTypeError("Supplied value should be a number");
8787
}
8888

89-
sass_color_set_r(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
89+
sass_color_set_r(Color::Unwrap<Color>(info.This())->value, Nan::To<double>(info[0]).FromJust());
9090
}
9191

9292
NAN_METHOD(Color::SetG) {
@@ -98,7 +98,7 @@ namespace SassTypes
9898
return Nan::ThrowTypeError("Supplied value should be a number");
9999
}
100100

101-
sass_color_set_g(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
101+
sass_color_set_g(Color::Unwrap<Color>(info.This())->value, Nan::To<double>(info[0]).FromJust());
102102
}
103103

104104
NAN_METHOD(Color::SetB) {
@@ -110,7 +110,7 @@ namespace SassTypes
110110
return Nan::ThrowTypeError("Supplied value should be a number");
111111
}
112112

113-
sass_color_set_b(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
113+
sass_color_set_b(Color::Unwrap<Color>(info.This())->value, Nan::To<double>(info[0]).FromJust());
114114
}
115115

116116
NAN_METHOD(Color::SetA) {
@@ -122,6 +122,6 @@ namespace SassTypes
122122
return Nan::ThrowTypeError("Supplied value should be a number");
123123
}
124124

125-
sass_color_set_a(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
125+
sass_color_set_a(Color::Unwrap<Color>(info.This())->value, Nan::To<double>(info[0]).FromJust());
126126
}
127127
}

src/sass_types/factory.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,12 @@ namespace SassTypes
6161
}
6262

6363
Value* Factory::unwrap(v8::Local<v8::Value> obj) {
64-
// Todo: non-SassValue objects could easily fall under that condition, need to be more specific.
65-
if (!obj->IsObject() || obj.As<v8::Object>()->InternalFieldCount() != 1) {
64+
if (obj->IsObject()) {
65+
v8::Local<v8::Object> v8_obj = obj.As<v8::Object>();
66+
if (v8_obj->InternalFieldCount() == 1) {
67+
return SassTypes::Value::Unwrap<Value>(v8_obj);
68+
}
69+
}
6670
return NULL;
67-
}
68-
69-
return static_cast<Value*>(Nan::GetInternalFieldPointer(obj.As<v8::Object>(), 0));
7071
}
7172
}

src/sass_types/list.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ namespace SassTypes
4747
return Nan::ThrowTypeError("Supplied index should be an integer");
4848
}
4949

50-
Sass_Value* list = unwrap(info.This())->value;
50+
Sass_Value* list = List::Unwrap<List>(info.This())->value;
5151
size_t index = Nan::To<uint32_t>(info[0]).FromJust();
5252

5353

@@ -73,14 +73,14 @@ namespace SassTypes
7373

7474
Value* sass_value = Factory::unwrap(info[1]);
7575
if (sass_value) {
76-
sass_list_set_value(unwrap(info.This())->value, Nan::To<uint32_t>(info[0]).FromJust(), sass_value->get_sass_value());
76+
sass_list_set_value(List::Unwrap<List>(info.This())->value, Nan::To<uint32_t>(info[0]).FromJust(), sass_value->get_sass_value());
7777
} else {
7878
Nan::ThrowTypeError("A SassValue is expected as the list item");
7979
}
8080
}
8181

8282
NAN_METHOD(List::GetSeparator) {
83-
info.GetReturnValue().Set(sass_list_get_separator(unwrap(info.This())->value) == SASS_COMMA);
83+
info.GetReturnValue().Set(sass_list_get_separator(List::Unwrap<List>(info.This())->value) == SASS_COMMA);
8484
}
8585

8686
NAN_METHOD(List::SetSeparator) {
@@ -92,10 +92,10 @@ namespace SassTypes
9292
return Nan::ThrowTypeError("Supplied value should be a boolean");
9393
}
9494

95-
sass_list_set_separator(unwrap(info.This())->value, Nan::To<bool>(info[0]).FromJust() ? SASS_COMMA : SASS_SPACE);
95+
sass_list_set_separator(List::Unwrap<List>(info.This())->value, Nan::To<bool>(info[0]).FromJust() ? SASS_COMMA : SASS_SPACE);
9696
}
9797

9898
NAN_METHOD(List::GetLength) {
99-
info.GetReturnValue().Set(Nan::New<v8::Number>(sass_list_get_length(unwrap(info.This())->value)));
99+
info.GetReturnValue().Set(Nan::New<v8::Number>(sass_list_get_length(List::Unwrap<List>(info.This())->value)));
100100
}
101101
}

0 commit comments

Comments
 (0)