Fix ObjectNotifierPerformChange leak after r21126

Due to overlapping names of natives and runtime functions, the wrong
context was used for Notifier.prototype.performChange. The leak test
has been augmented to properly cover the leaky case, and the test
now passes.

Also tightened up type checks in runtime.cc and removed Object.observe
functions from knownIssues in fuzz-natives-part2.js.

R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/264793015

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21129 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
adamk@chromium.org 2014-05-02 21:29:15 +00:00
parent 4dd8b11171
commit 5ea893074c
5 changed files with 27 additions and 22 deletions

View File

@ -365,7 +365,7 @@ function ObjectObserve(object, callback, acceptList) {
if (!AcceptArgIsValid(acceptList))
throw MakeTypeError("observe_accept_invalid");
return %NativeObjectObserve(object, callback, acceptList);
return %ObjectObserveInObjectContext(object, callback, acceptList);
}
function NativeObjectObserve(object, callback, acceptList) {
@ -539,7 +539,8 @@ function ObjectNotifierPerformChange(changeType, changeFn) {
if (!IS_SPEC_FUNCTION(changeFn))
throw MakeTypeError("observe_perform_non_function");
return %NativeObjectNotifierPerformChange(objectInfo, changeType, changeFn)
return %ObjectNotifierPerformChangeInObjectContext(
objectInfo, changeType, changeFn);
}
function NativeObjectNotifierPerformChange(objectInfo, changeType, changeFn) {
@ -566,7 +567,7 @@ function ObjectGetNotifier(object) {
if (!%ObjectWasCreatedInCurrentOrigin(object)) return null;
return %NativeObjectGetNotifier(object);
return %ObjectGetNotifierInObjectContext(object);
}
function NativeObjectGetNotifier(object) {

View File

@ -14996,12 +14996,13 @@ RUNTIME_FUNCTION(Runtime_ObjectWasCreatedInCurrentOrigin) {
}
RUNTIME_FUNCTION(Runtime_NativeObjectObserve) {
RUNTIME_FUNCTION(Runtime_ObjectObserveInObjectContext) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, callback, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, accept, 2);
RUNTIME_ASSERT(accept->IsUndefined() || accept->IsJSObject());
Handle<Context> context(object->GetCreationContext(), isolate);
Handle<JSFunction> function(context->native_object_observe(), isolate);
@ -15011,12 +15012,13 @@ RUNTIME_FUNCTION(Runtime_NativeObjectObserve) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
Execution::Call(isolate, function,
handle(context->object_function(), isolate), 3, call_args, true));
handle(context->object_function(), isolate),
ARRAY_SIZE(call_args), call_args, true));
return *result;
}
RUNTIME_FUNCTION(Runtime_NativeObjectGetNotifier) {
RUNTIME_FUNCTION(Runtime_ObjectGetNotifierInObjectContext) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
@ -15029,28 +15031,29 @@ RUNTIME_FUNCTION(Runtime_NativeObjectGetNotifier) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
Execution::Call(isolate, function,
handle(context->object_function(), isolate), 1, call_args, true));
handle(context->object_function(), isolate),
ARRAY_SIZE(call_args), call_args, true));
return *result;
}
RUNTIME_FUNCTION(Runtime_NativeObjectNotifierPerformChange) {
RUNTIME_FUNCTION(Runtime_ObjectNotifierPerformChangeInObjectContext) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object_info, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, change_type, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, change_fn, 2);
CONVERT_ARG_HANDLE_CHECKED(String, change_type, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, change_fn, 2);
Handle<Context> context(object_info->GetCreationContext(), isolate);
Handle<JSFunction> function(context->native_object_notifier_perform_change(),
isolate);
Handle<Object> call_args[] = { change_type, change_fn };
Handle<Object> call_args[] = { object_info, change_type, change_fn };
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
Execution::Call(isolate, function, isolate->factory()->undefined_value(),
2, call_args, true));
ARRAY_SIZE(call_args), call_args, true));
return *result;
}

View File

@ -313,8 +313,9 @@ namespace internal {
F(ObservationWeakMapCreate, 0, 1) \
F(ObserverObjectAndRecordHaveSameOrigin, 3, 1) \
F(ObjectWasCreatedInCurrentOrigin, 1, 1) \
F(NativeObjectObserve, 3, 1) \
F(NativeObjectGetNotifier, 1, 1) \
F(ObjectObserveInObjectContext, 3, 1) \
F(ObjectGetNotifierInObjectContext, 1, 1) \
F(ObjectNotifierPerformChangeInObjectContext, 3, 1) \
\
/* Harmony typed arrays */ \
F(ArrayBufferInitialize, 2, 1)\

View File

@ -692,14 +692,19 @@ TEST(DontLeakContextOnNotifierPerformChange) {
context->SetSecurityToken(foo);
CompileRun("var obj = {};");
Handle<Value> object = CompileRun("obj");
Handle<Value> notifier = CompileRun("Object.getNotifier(obj)");
{
HandleScope scope(CcTest::isolate());
LocalContext context2(CcTest::isolate());
context2->SetSecurityToken(foo);
context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
object);
CompileRun("var n = Object.getNotifier(obj);"
"n.performChange('foo', function() {});");
context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "notifier"),
notifier);
CompileRun("var obj2 = {};"
"var notifier2 = Object.getNotifier(obj2);"
"notifier2.performChange.call("
"notifier, 'foo', function(){})");
}
v8::V8::ContextDisposedNotification();

View File

@ -188,11 +188,6 @@ var knownProblems = {
// Only applicable to DataViews.
"_DataViewInitialize": true,
// Internal calls from the Object.observe API
"NativeObjectObserve": true,
"NativeObjectNotifierPerformChange": true,
"NativeObjectGetNotifier": true
};
var currentlyUncallable = {