build: move libcc patches to electron repo (#14104)

In the GN build, libchromiumcontent is no longer a distinct library, but
merely a container for a set of scripts and patches. Maintaining those
patches in a separate repository is tedious and error-prone, so merge
them into the main repo.

Once this is merged and GN is the default way to build Electron, the
libchromiumcontent repository can be archived.
This commit is contained in:
Jeremy Apthorp 2018-09-13 22:02:16 -07:00 committed by GitHub
parent 9e85bdb02c
commit 76c5f5cc8a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
147 changed files with 86931 additions and 6 deletions

View file

@ -0,0 +1,87 @@
repo: src/v8
patches:
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: add_realloc.patch
description: |
Blink overrides ArrayBuffer's allocator with its own one, while Node simply
uses malloc and free, so we need to use v8's allocator in Node. As part of the
10.6.0 upgrade, we needed to make SerializerDelegate accept an allocator
argument in its constructor, and override ReallocateBufferMemory and
FreeBufferMemory to use the allocator. We cannot simply allocate and then memcpy
when we override ReallocateBufferMemory, so we therefore need to implement
Realloc on the v8 side.
-
author: Ales Pergl <alpergl@microsoft.com>
file: build_gn.patch
description: null
-
author: Cheng Zhao <zcbenz@gmail.com>
file: array_buffer.patch
description: null
-
author: Cheng Zhao <zcbenz@gmail.com>
file: ostreams.patch
description: null
-
author: Aleksei Kuzmin <alkuzmin@microsoft.com>
file: export_platform.patch
description: |
v8::Platform::SystemClockTimeMillis must be exported so that node::NodePlatform can call it
-
author: Ales Pergl <alpergl@microsoft.com>
file: dcheck.patch
description: null
-
author: Nitish Sakhawalkar <nitsakh@icloud.com>
file: disable-warning-win.patch
description:
Disable unit test windows build warning
-
author: Aleksei Kuzmin <alkuzmin@microsoft.com>
file: backport_39d546a.patch
description: Node 10.0.0 needs it.
-
author: Aleksei Kuzmin <alkuzmin@microsoft.com>
file: backport_ff0a97933.patch
description: Node 10.2.0 needs it.
-
author: Aleksei Kuzmin <alkuzmin@microsoft.com>
file: backport_9fb02b526.patch
description: Node 10.2.0 needs it.
-
author: Aleksei Kuzmin <alkuzmin@microsoft.com>
file: backport_23652c5f.patch
description: Node 10.2.0 needs it.
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: backport_91ddb65d.patch
description: Node 10.6.0 needs it.
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: cherry-pick_6989b3f6d7.patch
description: Node 10.6.0 needs it.
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: cherry-pick_a440efb27f.patch
description: Node 10.6.0 needs it.
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: cherry-pick_5dd3395.patch
description: Node 10.6.0 needs it.
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: backport_aa6ce3e.patch
description: Node 10.6.0 needs it.
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: cherry-pick_b20faff.patch
description: Node 10.6.0 needs it.
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: cherry-pick_acc336c.patch
description: Node 10.6.0 needs it.
-
author: Shelley Vohr <shelley.vohr@gmail.com>
file: cherry-pick_70c4340.patch
description: Node 10.6.0 needs it.

View file

@ -0,0 +1,33 @@
diff --git a/include/v8.h b/include/v8.h
index 573e80176d..5eefe26fe9 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -4318,6 +4318,13 @@ class V8_EXPORT ArrayBuffer : public Object {
*/
virtual void* AllocateUninitialized(size_t length) = 0;
+ /**
+ * Free the memory block of size |length|, pointed to by |data|.
+ * That memory must be previously allocated by |Allocate| and not yet freed
+ * with a call to |Free| or |Realloc|
+ */
+ virtual void* Realloc(void* data, size_t length);
+
/**
* Free the memory block of size |length|, pointed to by |data|.
* That memory is guaranteed to be previously allocated by |Allocate|.
diff --git a/src/api.cc b/src/api.cc
index 8b177d041d..e06ca2a207 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -460,6 +460,10 @@ void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
i::V8::SetSnapshotBlob(snapshot_blob);
}
+void* v8::ArrayBuffer::Allocator::Realloc(void* data, size_t length) {
+ UNIMPLEMENTED();
+}
+
namespace {
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {

View file

@ -0,0 +1,32 @@
diff --git a/include/v8.h b/include/v8.h
index 573e80176d..80bfd1d22a 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -7337,6 +7337,9 @@ class V8_EXPORT Isolate {
*/
void SetIdle(bool is_idle);
+ /** Returns the ArrayBuffer::Allocator used in this isolate. */
+ ArrayBuffer::Allocator* GetArrayBufferAllocator();
+
/** Returns true if this isolate has a current context. */
bool InContext();
diff --git a/src/api.cc b/src/api.cc
index 8b177d041d..f58a350f0f 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -8139,6 +8139,13 @@ void Isolate::SetIdle(bool is_idle) {
isolate->SetIdle(is_idle);
}
+
+ArrayBuffer::Allocator* Isolate::GetArrayBufferAllocator() {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+ return isolate->array_buffer_allocator();
+}
+
+
bool Isolate::InContext() {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
return isolate->context() != nullptr;

View file

@ -0,0 +1,161 @@
23652c5f4cd07dd6304f78b407541c6a02caf60e
diff --git a/include/libplatform/v8-tracing.h b/include/libplatform/v8-tracing.h
index 9dcf3d7bca..e430e7c350 100644
--- a/include/libplatform/v8-tracing.h
+++ b/include/libplatform/v8-tracing.h
@@ -112,6 +112,8 @@ class V8_PLATFORM_EXPORT TraceWriter {
virtual void Flush() = 0;
static TraceWriter* CreateJSONTraceWriter(std::ostream& stream);
+ static TraceWriter* CreateJSONTraceWriter(std::ostream& stream,
+ const std::string& tag);
private:
// Disallow copy and assign
diff --git a/src/libplatform/tracing/trace-writer.cc b/src/libplatform/tracing/trace-writer.cc
index 36a8783499..7bfc766469 100644
--- a/src/libplatform/tracing/trace-writer.cc
+++ b/src/libplatform/tracing/trace-writer.cc
@@ -119,8 +119,12 @@ void JSONTraceWriter::AppendArgValue(ConvertableToTraceFormat* value) {
stream_ << arg_stringified;
}
-JSONTraceWriter::JSONTraceWriter(std::ostream& stream) : stream_(stream) {
- stream_ << "{\"traceEvents\":[";
+JSONTraceWriter::JSONTraceWriter(std::ostream& stream)
+ : JSONTraceWriter(stream, "traceEvents") {}
+
+JSONTraceWriter::JSONTraceWriter(std::ostream& stream, const std::string& tag)
+ : stream_(stream) {
+ stream_ << "{\"" << tag << "\":[";
}
JSONTraceWriter::~JSONTraceWriter() { stream_ << "]}"; }
@@ -171,6 +175,11 @@ TraceWriter* TraceWriter::CreateJSONTraceWriter(std::ostream& stream) {
return new JSONTraceWriter(stream);
}
+TraceWriter* TraceWriter::CreateJSONTraceWriter(std::ostream& stream,
+ const std::string& tag) {
+ return new JSONTraceWriter(stream, tag);
+}
+
} // namespace tracing
} // namespace platform
} // namespace v8
diff --git a/src/libplatform/tracing/trace-writer.h b/src/libplatform/tracing/trace-writer.h
index 7e1bdc24d6..d811351389 100644
--- a/src/libplatform/tracing/trace-writer.h
+++ b/src/libplatform/tracing/trace-writer.h
@@ -14,6 +14,7 @@ namespace tracing {
class JSONTraceWriter : public TraceWriter {
public:
explicit JSONTraceWriter(std::ostream& stream);
+ JSONTraceWriter(std::ostream& stream, const std::string& tag);
~JSONTraceWriter();
void AppendTraceEvent(TraceObject* trace_event) override;
void Flush() override;
diff --git a/test/cctest/libplatform/test-tracing.cc b/test/cctest/libplatform/test-tracing.cc
index da202057de..b949785bcf 100644
--- a/test/cctest/libplatform/test-tracing.cc
+++ b/test/cctest/libplatform/test-tracing.cc
@@ -128,44 +128,42 @@ TEST(TestTraceBufferRingBuffer) {
delete ring_buffer;
}
-TEST(TestJSONTraceWriter) {
- std::ostringstream stream;
- // Create a scope for the tracing controller to terminate the trace writer.
- {
- v8::Platform* old_platform = i::V8::GetCurrentPlatform();
- std::unique_ptr<v8::Platform> default_platform(
- v8::platform::NewDefaultPlatform());
- i::V8::SetPlatformForTesting(default_platform.get());
- auto tracing =
- base::make_unique<v8::platform::tracing::TracingController>();
- v8::platform::tracing::TracingController* tracing_controller =
- tracing.get();
- static_cast<v8::platform::DefaultPlatform*>(default_platform.get())
- ->SetTracingController(std::move(tracing));
- TraceWriter* writer = TraceWriter::CreateJSONTraceWriter(stream);
+void PopulateJSONWriter(TraceWriter* writer) {
+ v8::Platform* old_platform = i::V8::GetCurrentPlatform();
+ std::unique_ptr<v8::Platform> default_platform(
+ v8::platform::NewDefaultPlatform());
+ i::V8::SetPlatformForTesting(default_platform.get());
+ auto tracing = base::make_unique<v8::platform::tracing::TracingController>();
+ v8::platform::tracing::TracingController* tracing_controller = tracing.get();
+ static_cast<v8::platform::DefaultPlatform*>(default_platform.get())
+ ->SetTracingController(std::move(tracing));
- TraceBuffer* ring_buffer =
- TraceBuffer::CreateTraceBufferRingBuffer(1, writer);
- tracing_controller->Initialize(ring_buffer);
- TraceConfig* trace_config = new TraceConfig();
- trace_config->AddIncludedCategory("v8-cat");
- tracing_controller->StartTracing(trace_config);
+ TraceBuffer* ring_buffer =
+ TraceBuffer::CreateTraceBufferRingBuffer(1, writer);
+ tracing_controller->Initialize(ring_buffer);
+ TraceConfig* trace_config = new TraceConfig();
+ trace_config->AddIncludedCategory("v8-cat");
+ tracing_controller->StartTracing(trace_config);
- TraceObject trace_object;
- trace_object.InitializeForTesting(
- 'X', tracing_controller->GetCategoryGroupEnabled("v8-cat"), "Test0",
- v8::internal::tracing::kGlobalScope, 42, 123, 0, nullptr, nullptr,
- nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID, 11, 22, 100, 50, 33, 44);
- writer->AppendTraceEvent(&trace_object);
- trace_object.InitializeForTesting(
- 'Y', tracing_controller->GetCategoryGroupEnabled("v8-cat"), "Test1",
- v8::internal::tracing::kGlobalScope, 43, 456, 0, nullptr, nullptr,
- nullptr, nullptr, 0, 55, 66, 110, 55, 77, 88);
- writer->AppendTraceEvent(&trace_object);
- tracing_controller->StopTracing();
- i::V8::SetPlatformForTesting(old_platform);
- }
+ TraceObject trace_object;
+ trace_object.InitializeForTesting(
+ 'X', tracing_controller->GetCategoryGroupEnabled("v8-cat"), "Test0",
+ v8::internal::tracing::kGlobalScope, 42, 123, 0, nullptr, nullptr,
+ nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID, 11, 22, 100, 50, 33, 44);
+ writer->AppendTraceEvent(&trace_object);
+ trace_object.InitializeForTesting(
+ 'Y', tracing_controller->GetCategoryGroupEnabled("v8-cat"), "Test1",
+ v8::internal::tracing::kGlobalScope, 43, 456, 0, nullptr, nullptr,
+ nullptr, nullptr, 0, 55, 66, 110, 55, 77, 88);
+ writer->AppendTraceEvent(&trace_object);
+ tracing_controller->StopTracing();
+ i::V8::SetPlatformForTesting(old_platform);
+}
+TEST(TestJSONTraceWriter) {
+ std::ostringstream stream;
+ TraceWriter* writer = TraceWriter::CreateJSONTraceWriter(stream);
+ PopulateJSONWriter(writer);
std::string trace_str = stream.str();
std::string expected_trace_str =
"{\"traceEvents\":[{\"pid\":11,\"tid\":22,\"ts\":100,\"tts\":50,"
@@ -177,6 +175,21 @@ TEST(TestJSONTraceWriter) {
CHECK_EQ(expected_trace_str, trace_str);
}
+TEST(TestJSONTraceWriterWithCustomtag) {
+ std::ostringstream stream;
+ TraceWriter* writer = TraceWriter::CreateJSONTraceWriter(stream, "customTag");
+ PopulateJSONWriter(writer);
+ std::string trace_str = stream.str();
+ std::string expected_trace_str =
+ "{\"customTag\":[{\"pid\":11,\"tid\":22,\"ts\":100,\"tts\":50,"
+ "\"ph\":\"X\",\"cat\":\"v8-cat\",\"name\":\"Test0\",\"dur\":33,"
+ "\"tdur\":44,\"id\":\"0x2a\",\"args\":{}},{\"pid\":55,\"tid\":66,"
+ "\"ts\":110,\"tts\":55,\"ph\":\"Y\",\"cat\":\"v8-cat\",\"name\":"
+ "\"Test1\",\"dur\":77,\"tdur\":88,\"args\":{}}]}";
+
+ CHECK_EQ(expected_trace_str, trace_str);
+}
+
TEST(TestTracingController) {
v8::Platform* old_platform = i::V8::GetCurrentPlatform();
std::unique_ptr<v8::Platform> default_platform(

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,84 @@
39d546a24022b62b00aedf7b556ac6c9e2306aab
diff --git a/AUTHORS b/AUTHORS
index 3251716f2a..4b5163961d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -70,6 +70,7 @@ Felix Geisendörfer <haimuiba@gmail.com>
Filipe David Manana <fdmanana@gmail.com>
Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Geoffrey Garside <ggarside@gmail.com>
+Gus Caplan <me@gus.host>
Gwang Yoon Hwang <ryumiel@company100.net>
Henrique Ferreiro <henrique.ferreiro@gmail.com>
Hirofumi Mako <mkhrfm@gmail.com>
diff --git a/include/v8.h b/include/v8.h
index 573e80176d..aeeebba304 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2378,6 +2378,11 @@ class V8_EXPORT Value : public Data {
bool IsWebAssemblyCompiledModule() const;
+ /**
+ * Returns true if the value is a Module Namespace Object.
+ */
+ bool IsModuleNamespaceObject() const;
+
V8_WARN_UNUSED_RESULT MaybeLocal<BigInt> ToBigInt(
Local<Context> context) const;
V8_WARN_UNUSED_RESULT MaybeLocal<Boolean> ToBoolean(
diff --git a/src/api.cc b/src/api.cc
index 8b177d041d..6dd669ee11 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -3583,6 +3583,10 @@ bool Value::IsSetIterator() const {
bool Value::IsPromise() const { return Utils::OpenHandle(this)->IsJSPromise(); }
+bool Value::IsModuleNamespaceObject() const {
+ return Utils::OpenHandle(this)->IsJSModuleNamespace();
+}
+
MaybeLocal<String> Value::ToString(Local<Context> context) const {
auto obj = Utils::OpenHandle(this);
if (obj->IsString()) return ToApiHandle<String>(obj);
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 54afc61f4c..b7483a7c5e 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -27239,6 +27239,35 @@ TEST(ImportMeta) {
CHECK(result->StrictEquals(Local<v8::Value>::Cast(v8::Utils::ToLocal(meta))));
}
+TEST(GetModuleNamespace) {
+ LocalContext context;
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ Local<String> url = v8_str("www.google.com");
+ Local<String> source_text = v8_str("export default 5; export const a = 10;");
+ v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
+ Local<v8::Boolean>(), Local<v8::Integer>(),
+ Local<v8::Value>(), Local<v8::Boolean>(),
+ Local<v8::Boolean>(), True(isolate));
+ v8::ScriptCompiler::Source source(source_text, origin);
+ Local<Module> module =
+ v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
+ module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
+ .ToChecked();
+ module->Evaluate(context.local()).ToLocalChecked();
+
+ Local<Value> ns_val = module->GetModuleNamespace();
+ CHECK(ns_val->IsModuleNamespaceObject());
+ Local<Object> ns = ns_val.As<Object>();
+ CHECK(ns->Get(context.local(), v8_str("default"))
+ .ToLocalChecked()
+ ->StrictEquals(v8::Number::New(isolate, 5)));
+ CHECK(ns->Get(context.local(), v8_str("a"))
+ .ToLocalChecked()
+ ->StrictEquals(v8::Number::New(isolate, 10)));
+}
+
TEST(GlobalTemplateWithDoubleProperty) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope handle_scope(isolate);

View file

@ -0,0 +1,235 @@
From 5020630808043615f2f6fbbfba1ea73342bebd69 Mon Sep 17 00:00:00 2001
From: Daniel Clifford <danno@chromium.org>
Date: Wed, 28 Mar 2018 13:30:16 +0200
Subject: [PATCH] Remove legacy C++ implementation of Array#slice
Change-Id: Ifdeda00ad55aa937a6a414e7e566e6640ccd83c0
Reviewed-on: https://chromium-review.googlesource.com/980936
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Daniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52278}
---
src/bootstrapper.cc | 8 ++---
src/builtins/builtins-array.cc | 69 -------------------------------------
src/builtins/builtins-definitions.h | 1 -
src/contexts.h | 1 -
src/debug/debug-evaluate.cc | 1 -
src/flag-definitions.h | 2 +-
src/js/array.js | 43 +++--------------------
7 files changed, 8 insertions(+), 117 deletions(-)
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 95d98078f3..626251202d 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1658,12 +1658,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(proto, "shift", Builtins::kArrayPrototypeShift, 0,
false);
SimpleInstallFunction(proto, "unshift", Builtins::kArrayUnshift, 1, false);
- if (FLAG_enable_experimental_builtins) {
- SimpleInstallFunction(proto, "slice", Builtins::kArrayPrototypeSlice, 2,
- false);
- } else {
- SimpleInstallFunction(proto, "slice", Builtins::kArraySlice, 2, false);
- }
+ SimpleInstallFunction(proto, "slice", Builtins::kArrayPrototypeSlice, 2,
+ false);
SimpleInstallFunction(proto, "splice", Builtins::kArraySplice, 2, false);
SimpleInstallFunction(proto, "includes", Builtins::kArrayIncludes, 1,
false);
diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc
index f400e824f0..7e3f948cbe 100644
--- a/src/builtins/builtins-array.cc
+++ b/src/builtins/builtins-array.cc
@@ -240,75 +240,6 @@ BUILTIN(ArrayUnshift) {
return Smi::FromInt(new_length);
}
-BUILTIN(ArraySlice) {
- HandleScope scope(isolate);
- Handle<Object> receiver = args.receiver();
- int len = -1;
- int relative_start = 0;
- int relative_end = 0;
-
- if (receiver->IsJSArray()) {
- DisallowHeapAllocation no_gc;
- JSArray* array = JSArray::cast(*receiver);
- if (V8_UNLIKELY(!array->HasFastElements() ||
- !IsJSArrayFastElementMovingAllowed(isolate, array) ||
- !isolate->IsSpeciesLookupChainIntact() ||
- // If this is a subclass of Array, then call out to JS
- !array->HasArrayPrototype(isolate))) {
- AllowHeapAllocation allow_allocation;
- return CallJsIntrinsic(isolate, isolate->array_slice(), args);
- }
- len = Smi::ToInt(array->length());
- } else if (receiver->IsJSObject() &&
- JSSloppyArgumentsObject::GetSloppyArgumentsLength(
- isolate, Handle<JSObject>::cast(receiver), &len)) {
- // Array.prototype.slice.call(arguments, ...) is quite a common idiom
- // (notably more than 50% of invocations in Web apps).
- // Treat it in C++ as well.
- DCHECK(JSObject::cast(*receiver)->HasFastElements() ||
- JSObject::cast(*receiver)->HasFastArgumentsElements());
- } else {
- AllowHeapAllocation allow_allocation;
- return CallJsIntrinsic(isolate, isolate->array_slice(), args);
- }
- DCHECK_LE(0, len);
- int argument_count = args.length() - 1;
- // Note carefully chosen defaults---if argument is missing,
- // it's undefined which gets converted to 0 for relative_start
- // and to len for relative_end.
- relative_start = 0;
- relative_end = len;
- if (argument_count > 0) {
- DisallowHeapAllocation no_gc;
- if (!ClampedToInteger(isolate, args[1], &relative_start)) {
- AllowHeapAllocation allow_allocation;
- return CallJsIntrinsic(isolate, isolate->array_slice(), args);
- }
- if (argument_count > 1) {
- Object* end_arg = args[2];
- // slice handles the end_arg specially
- if (end_arg->IsUndefined(isolate)) {
- relative_end = len;
- } else if (!ClampedToInteger(isolate, end_arg, &relative_end)) {
- AllowHeapAllocation allow_allocation;
- return CallJsIntrinsic(isolate, isolate->array_slice(), args);
- }
- }
- }
-
- // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
- uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
- : Min(relative_start, len);
-
- // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
- uint32_t actual_end =
- (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len);
-
- Handle<JSObject> object = Handle<JSObject>::cast(receiver);
- ElementsAccessor* accessor = object->GetElementsAccessor();
- return *accessor->Slice(object, actual_start, actual_end);
-}
-
BUILTIN(ArraySplice) {
HandleScope scope(isolate);
Handle<Object> receiver = args.receiver();
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
index f31cf707cb..5d2b160f78 100644
--- a/src/builtins/builtins-definitions.h
+++ b/src/builtins/builtins-definitions.h
@@ -269,7 +269,6 @@ namespace internal {
CPP(ArrayShift) \
TFJ(ArrayPrototypeShift, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.slice */ \
- CPP(ArraySlice) \
TFJ(ArrayPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.splice */ \
CPP(ArraySplice) \
diff --git a/src/contexts.h b/src/contexts.h
index 03b32ab586..bb55d91c9c 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -69,7 +69,6 @@ enum ContextLookupFlags {
V(ARRAY_PUSH_INDEX, JSFunction, array_push) \
V(ARRAY_SHIFT_INDEX, JSFunction, array_shift) \
V(ARRAY_SPLICE_INDEX, JSFunction, array_splice) \
- V(ARRAY_SLICE_INDEX, JSFunction, array_slice) \
V(ARRAY_UNSHIFT_INDEX, JSFunction, array_unshift) \
V(ARRAY_ENTRIES_ITERATOR_INDEX, JSFunction, array_entries_iterator) \
V(ARRAY_FOR_EACH_ITERATOR_INDEX, JSFunction, array_for_each_iterator) \
diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc
index c937be4fe0..d9defc778c 100644
--- a/src/debug/debug-evaluate.cc
+++ b/src/debug/debug-evaluate.cc
@@ -616,7 +616,6 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) {
case Builtins::kArrayEvery:
case Builtins::kArraySome:
case Builtins::kArrayConcat:
- case Builtins::kArraySlice:
case Builtins::kArrayFilter:
case Builtins::kArrayMap:
case Builtins::kArrayReduce:
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 21cd9b2d3c..a05571700f 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -832,7 +832,7 @@ DEFINE_BOOL(expose_trigger_failure, false, "expose trigger-failure extension")
DEFINE_INT(stack_trace_limit, 10, "number of stack frames to capture")
DEFINE_BOOL(builtins_in_stack_traces, false,
"show built-in functions in stack traces")
-DEFINE_BOOL(enable_experimental_builtins, true,
+DEFINE_BOOL(enable_experimental_builtins, false,
"enable new csa-based experimental builtins")
DEFINE_BOOL(disallow_code_generation_from_strings, false,
"disallow eval and friends")
diff --git a/src/js/array.js b/src/js/array.js
index c293f8e8c8..5b393263da 100644
--- a/src/js/array.js
+++ b/src/js/array.js
@@ -578,46 +578,14 @@ function ArrayUnshiftFallback(arg1) { // length == 1
}
+// Oh the humanity... don't remove the following function because js2c for some
+// reason gets symbol minifiation wrong if it's not there. Instead of spending
+// the time fixing js2c (which will go away when all of the internal .js runtime
+// files are gone), just keep this work-around.
function ArraySliceFallback(start, end) {
- var array = TO_OBJECT(this);
- var len = TO_LENGTH(array.length);
- var start_i = TO_INTEGER(start);
- var end_i = len;
-
- if (!IS_UNDEFINED(end)) end_i = TO_INTEGER(end);
-
- if (start_i < 0) {
- start_i += len;
- if (start_i < 0) start_i = 0;
- } else {
- if (start_i > len) start_i = len;
- }
-
- if (end_i < 0) {
- end_i += len;
- if (end_i < 0) end_i = 0;
- } else {
- if (end_i > len) end_i = len;
- }
-
- var result = ArraySpeciesCreate(array, MathMax(end_i - start_i, 0));
-
- if (end_i < start_i) return result;
-
- if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) {
- %NormalizeElements(array);
- if (IS_ARRAY(result)) %NormalizeElements(result);
- SparseSlice(array, start_i, end_i - start_i, len, result);
- } else {
- SimpleSlice(array, start_i, end_i - start_i, len, result);
- }
-
- result.length = end_i - start_i;
-
- return result;
+ return null;
}
-
function ComputeSpliceStartIndex(start_i, len) {
if (start_i < 0) {
start_i += len;
@@ -1229,7 +1197,6 @@ utils.Export(function(to) {
"array_push", ArrayPushFallback,
"array_shift", ArrayShiftFallback,
"array_splice", ArraySpliceFallback,
- "array_slice", ArraySliceFallback,
"array_unshift", ArrayUnshiftFallback,
]);
--
2.11.0 (Apple Git-81)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,114 @@
9fb02b526f1cd3b859a530a01adb08bc0d089f4f
diff --git a/src/builtins/builtins-api.cc b/src/builtins/builtins-api.cc
index 7e2d3e219e..c26c1a9fd1 100644
--- a/src/builtins/builtins-api.cc
+++ b/src/builtins/builtins-api.cc
@@ -22,17 +22,21 @@ namespace {
// Returns the holder JSObject if the function can legally be called with this
// receiver. Returns nullptr if the call is illegal.
// TODO(dcarney): CallOptimization duplicates this logic, merge.
-JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info,
- JSObject* receiver) {
+JSReceiver* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info,
+ JSReceiver* receiver) {
Object* recv_type = info->signature();
// No signature, return holder.
if (!recv_type->IsFunctionTemplateInfo()) return receiver;
+ // A Proxy cannot have been created from the signature template.
+ if (!receiver->IsJSObject()) return nullptr;
+
+ JSObject* js_obj_receiver = JSObject::cast(receiver);
FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
// Check the receiver. Fast path for receivers with no hidden prototypes.
- if (signature->IsTemplateFor(receiver)) return receiver;
- if (!receiver->map()->has_hidden_prototype()) return nullptr;
- for (PrototypeIterator iter(isolate, receiver, kStartAtPrototype,
+ if (signature->IsTemplateFor(js_obj_receiver)) return receiver;
+ if (!js_obj_receiver->map()->has_hidden_prototype()) return nullptr;
+ for (PrototypeIterator iter(isolate, js_obj_receiver, kStartAtPrototype,
PrototypeIterator::END_AT_NON_HIDDEN);
!iter.IsAtEnd(); iter.Advance()) {
JSObject* current = iter.GetCurrent<JSObject>();
@@ -46,8 +50,8 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> HandleApiCallHelper(
Isolate* isolate, Handle<HeapObject> function,
Handle<HeapObject> new_target, Handle<FunctionTemplateInfo> fun_data,
Handle<Object> receiver, BuiltinArguments args) {
- Handle<JSObject> js_receiver;
- JSObject* raw_holder;
+ Handle<JSReceiver> js_receiver;
+ JSReceiver* raw_holder;
if (is_construct) {
DCHECK(args.receiver()->IsTheHole(isolate));
if (fun_data->instance_template()->IsUndefined(isolate)) {
@@ -69,21 +73,18 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> HandleApiCallHelper(
raw_holder = *js_receiver;
} else {
DCHECK(receiver->IsJSReceiver());
-
- if (!receiver->IsJSObject()) {
- // This function cannot be called with the given receiver. Abort!
- THROW_NEW_ERROR(
- isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
- }
-
- js_receiver = Handle<JSObject>::cast(receiver);
+ js_receiver = Handle<JSReceiver>::cast(receiver);
if (!fun_data->accept_any_receiver() &&
- js_receiver->IsAccessCheckNeeded() &&
- !isolate->MayAccess(handle(isolate->context()), js_receiver)) {
- isolate->ReportFailedAccessCheck(js_receiver);
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
- return isolate->factory()->undefined_value();
+ js_receiver->IsAccessCheckNeeded()) {
+ // Proxies never need access checks.
+ DCHECK(js_receiver->IsJSObject());
+ Handle<JSObject> js_obj_receiver = Handle<JSObject>::cast(js_receiver);
+ if (!isolate->MayAccess(handle(isolate->context()), js_obj_receiver)) {
+ isolate->ReportFailedAccessCheck(js_obj_receiver);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ return isolate->factory()->undefined_value();
+ }
}
raw_holder = GetCompatibleReceiver(isolate, *fun_data, *js_receiver);
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 7887cbfa75..0605f439e5 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -1088,6 +1088,34 @@ THREADED_PROFILED_TEST(FunctionTemplate) {
TestFunctionTemplateAccessor(construct_callback, Return239Callback);
}
+static void FunctionCallbackForProxyTest(
+ const v8::FunctionCallbackInfo<Value>& info) {
+ info.GetReturnValue().Set(info.This());
+}
+
+THREADED_TEST(FunctionTemplateWithProxy) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ v8::Local<v8::FunctionTemplate> function_template =
+ v8::FunctionTemplate::New(isolate, FunctionCallbackForProxyTest);
+ v8::Local<v8::Function> function =
+ function_template->GetFunction(env.local()).ToLocalChecked();
+ CHECK((*env)->Global()->Set(env.local(), v8_str("f"), function).FromJust());
+ v8::Local<v8::Value> proxy =
+ CompileRun("var proxy = new Proxy({}, {}); proxy");
+ CHECK(proxy->IsProxy());
+
+ v8::Local<v8::Value> result = CompileRun("f(proxy)");
+ CHECK(result->Equals(env.local(), (*env)->Global()).FromJust());
+
+ result = CompileRun("f.call(proxy)");
+ CHECK(result->Equals(env.local(), proxy).FromJust());
+
+ result = CompileRun("Reflect.apply(f, proxy, [1])");
+ CHECK(result->Equals(env.local(), proxy).FromJust());
+}
static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
ApiTestFuzzer::Fuzz();

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,284 @@
diff --git a/src/isolate.cc b/src/isolate.cc
index 38506bfc25..37a5578763 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -8,6 +8,7 @@
#include <fstream> // NOLINT(readability/streams)
#include <sstream>
+#include <unordered_map>
#include "src/api.h"
#include "src/assembler-inl.h"
@@ -136,8 +137,6 @@ void ThreadLocalTop::Free() {
base::Thread::LocalStorageKey Isolate::isolate_key_;
base::Thread::LocalStorageKey Isolate::thread_id_key_;
base::Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
-base::LazyMutex Isolate::thread_data_table_mutex_ = LAZY_MUTEX_INITIALIZER;
-Isolate::ThreadDataTable* Isolate::thread_data_table_ = nullptr;
base::Atomic32 Isolate::isolate_counter_ = 0;
#if DEBUG
base::Atomic32 Isolate::isolate_key_created_ = 0;
@@ -148,13 +147,13 @@ Isolate::PerIsolateThreadData*
ThreadId thread_id = ThreadId::Current();
PerIsolateThreadData* per_thread = nullptr;
{
- base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
- per_thread = thread_data_table_->Lookup(this, thread_id);
+ base::LockGuard<base::Mutex> lock_guard(&thread_data_table_mutex_);
+ per_thread = thread_data_table_.Lookup(thread_id);
if (per_thread == nullptr) {
per_thread = new PerIsolateThreadData(this, thread_id);
- thread_data_table_->Insert(per_thread);
+ thread_data_table_.Insert(per_thread);
}
- DCHECK(thread_data_table_->Lookup(this, thread_id) == per_thread);
+ DCHECK(thread_data_table_.Lookup(thread_id) == per_thread);
}
return per_thread;
}
@@ -165,12 +164,11 @@ void Isolate::DiscardPerThreadDataForThisThread() {
if (thread_id_int) {
ThreadId thread_id = ThreadId(thread_id_int);
DCHECK(!thread_manager_->mutex_owner_.Equals(thread_id));
- base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
- PerIsolateThreadData* per_thread =
- thread_data_table_->Lookup(this, thread_id);
+ base::LockGuard<base::Mutex> lock_guard(&thread_data_table_mutex_);
+ PerIsolateThreadData* per_thread = thread_data_table_.Lookup(thread_id);
if (per_thread) {
DCHECK(!per_thread->thread_state_);
- thread_data_table_->Remove(per_thread);
+ thread_data_table_.Remove(per_thread);
}
}
}
@@ -186,23 +184,20 @@ Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread(
ThreadId thread_id) {
PerIsolateThreadData* per_thread = nullptr;
{
- base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
- per_thread = thread_data_table_->Lookup(this, thread_id);
+ base::LockGuard<base::Mutex> lock_guard(&thread_data_table_mutex_);
+ per_thread = thread_data_table_.Lookup(thread_id);
}
return per_thread;
}
void Isolate::InitializeOncePerProcess() {
- base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
- CHECK_NULL(thread_data_table_);
isolate_key_ = base::Thread::CreateThreadLocalKey();
#if DEBUG
base::Relaxed_Store(&isolate_key_created_, 1);
#endif
thread_id_key_ = base::Thread::CreateThreadLocalKey();
per_isolate_thread_data_key_ = base::Thread::CreateThreadLocalKey();
- thread_data_table_ = new Isolate::ThreadDataTable();
}
Address Isolate::get_address_from_id(IsolateAddressId id) {
@@ -2240,14 +2235,9 @@ char* Isolate::RestoreThread(char* from) {
return from + sizeof(ThreadLocalTop);
}
-Isolate::ThreadDataTable::ThreadDataTable() : list_(nullptr) {}
+Isolate::ThreadDataTable::ThreadDataTable() : table_() {}
-Isolate::ThreadDataTable::~ThreadDataTable() {
- // TODO(svenpanne) The assertion below would fire if an embedder does not
- // cleanly dispose all Isolates before disposing v8, so we are conservative
- // and leave it out for now.
- // DCHECK_NULL(list_);
-}
+Isolate::ThreadDataTable::~ThreadDataTable() {}
void Isolate::ReleaseManagedObjects() {
Isolate::ManagedObjectFinalizer* current =
@@ -2294,40 +2284,30 @@ Isolate::PerIsolateThreadData::~PerIsolateThreadData() {
#endif
}
-
-Isolate::PerIsolateThreadData*
- Isolate::ThreadDataTable::Lookup(Isolate* isolate,
- ThreadId thread_id) {
- for (PerIsolateThreadData* data = list_; data != nullptr;
- data = data->next_) {
- if (data->Matches(isolate, thread_id)) return data;
- }
- return nullptr;
+Isolate::PerIsolateThreadData* Isolate::ThreadDataTable::Lookup(
+ ThreadId thread_id) {
+ auto t = table_.find(thread_id);
+ if (t == table_.end()) return nullptr;
+ return t->second;
}
void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
- if (list_ != nullptr) list_->prev_ = data;
- data->next_ = list_;
- list_ = data;
+ bool inserted = table_.insert(std::make_pair(data->thread_id_, data)).second;
+ CHECK(inserted);
}
void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
- if (list_ == data) list_ = data->next_;
- if (data->next_ != nullptr) data->next_->prev_ = data->prev_;
- if (data->prev_ != nullptr) data->prev_->next_ = data->next_;
+ table_.erase(data->thread_id_);
delete data;
}
-
-void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) {
- PerIsolateThreadData* data = list_;
- while (data != nullptr) {
- PerIsolateThreadData* next = data->next_;
- if (data->isolate() == isolate) Remove(data);
- data = next;
+void Isolate::ThreadDataTable::RemoveAllThreads() {
+ for (auto& x : table_) {
+ delete x.second;
}
+ table_.clear();
}
@@ -2502,10 +2482,6 @@ Isolate::Isolate(bool enable_serializer)
cancelable_task_manager_(new CancelableTaskManager()),
abort_on_uncaught_exception_callback_(nullptr),
total_regexp_code_generated_(0) {
- {
- base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
- CHECK(thread_data_table_);
- }
id_ = base::Relaxed_AtomicIncrement(&isolate_counter_, 1);
TRACE_ISOLATE(constructor);
@@ -2563,8 +2539,8 @@ void Isolate::TearDown() {
Deinit();
{
- base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
- thread_data_table_->RemoveAllThreads(this);
+ base::LockGuard<base::Mutex> lock_guard(&thread_data_table_mutex_);
+ thread_data_table_.RemoveAllThreads();
}
#ifdef DEBUG
@@ -2578,12 +2554,6 @@ void Isolate::TearDown() {
}
-void Isolate::GlobalTearDown() {
- delete thread_data_table_;
- thread_data_table_ = nullptr;
-}
-
-
void Isolate::ClearSerializerData() {
delete external_reference_table_;
external_reference_table_ = nullptr;
diff --git a/src/isolate.h b/src/isolate.h
index 5538992af1..40135ef324 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -8,6 +8,7 @@
#include <cstddef>
#include <memory>
#include <queue>
+#include <unordered_map>
#include <vector>
#include "include/v8.h"
@@ -247,6 +248,8 @@ class ThreadId {
return *this;
}
+ bool operator==(const ThreadId& other) const { return Equals(other); }
+
// Returns ThreadId for current thread.
static ThreadId Current() { return ThreadId(GetCurrentThreadId()); }
@@ -287,7 +290,6 @@ class ThreadId {
friend class Isolate;
};
-
#define FIELD_ACCESSOR(type, name) \
inline void set_##name(type v) { name##_ = v; } \
inline type name() const { return name##_; }
@@ -550,8 +552,6 @@ class Isolate {
void ReleaseManagedObjects();
- static void GlobalTearDown();
-
void ClearSerializerData();
// Find the PerThread for this particular (isolate, thread) combination
@@ -1371,20 +1371,24 @@ class Isolate {
void* embedder_data_[Internals::kNumIsolateDataSlots];
Heap heap_;
- // The per-process lock should be acquired before the ThreadDataTable is
- // modified.
class ThreadDataTable {
public:
ThreadDataTable();
~ThreadDataTable();
- PerIsolateThreadData* Lookup(Isolate* isolate, ThreadId thread_id);
+ PerIsolateThreadData* Lookup(ThreadId thread_id);
void Insert(PerIsolateThreadData* data);
void Remove(PerIsolateThreadData* data);
- void RemoveAllThreads(Isolate* isolate);
+ void RemoveAllThreads();
private:
- PerIsolateThreadData* list_;
+ struct Hasher {
+ std::size_t operator()(const ThreadId& t) const {
+ return std::hash<int>()(t.ToInteger());
+ }
+ };
+
+ std::unordered_map<ThreadId, PerIsolateThreadData*, Hasher> table_;
};
// These items form a stack synchronously with threads Enter'ing and Exit'ing
@@ -1412,12 +1416,15 @@ class Isolate {
DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
};
- static base::LazyMutex thread_data_table_mutex_;
+ // TODO(kenton@cloudflare.com): This mutex can be removed if
+ // thread_data_table_ is always accessed under the isolate lock. I do not
+ // know if this is the case, so I'm preserving it for now.
+ base::Mutex thread_data_table_mutex_;
static base::Thread::LocalStorageKey per_isolate_thread_data_key_;
static base::Thread::LocalStorageKey isolate_key_;
static base::Thread::LocalStorageKey thread_id_key_;
- static ThreadDataTable* thread_data_table_;
+ ThreadDataTable thread_data_table_;
// A global counter for all generated Isolates, might overflow.
static base::Atomic32 isolate_counter_;
diff --git a/src/v8.cc b/src/v8.cc
index ab4918efec..d3b4c471a4 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -49,7 +49,6 @@ void V8::TearDown() {
Bootstrapper::TearDownExtensions();
ElementsAccessor::TearDown();
RegisteredExtension::UnregisterAll();
- Isolate::GlobalTearDown();
sampler::Sampler::TearDown();
FlagList::ResetAllFlags(); // Frees memory held by string arguments.
}

View file

@ -0,0 +1,15 @@
b767cde1e7bb94b3fea13f2d7e10cd90e6813d6c
diff --git a/src/runtime/runtime-intl.cc b/src/runtime/runtime-intl.cc
index c359a1e5a1..198610a652 100644
--- a/src/runtime/runtime-intl.cc
+++ b/src/runtime/runtime-intl.cc
@@ -620,8 +620,7 @@ RUNTIME_FUNCTION(Runtime_PluralRulesSelect) {
icu::UnicodeString result = plural_rules->select(rounded);
return *isolate->factory()
->NewStringFromTwoByte(Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(
- icu::toUCharPtr(result.getBuffer())),
+ reinterpret_cast<const uint16_t*>(result.getBuffer()),
result.length()))
.ToHandleChecked();
}

View file

@ -0,0 +1,88 @@
diff --git a/include/v8.h b/include/v8.h
index 573e80176d..bb77987f14 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -3544,6 +3549,17 @@ class V8_EXPORT Object : public Value {
*/
Isolate* GetIsolate();
+ /**
+ * If this object is a Set, Map, WeakSet or WeakMap, this returns a
+ * representation of the elements of this object as an array.
+ * If this object is a SetIterator or MapIterator, this returns all
+ * elements of the underlying collection, starting at the iterator's current
+ * position.
+ * For other types, this will return an empty MaybeLocal<Array> (without
+ * scheduling an exception).
+ */
+ MaybeLocal<Array> PreviewEntries(bool* is_key_value);
+
static Local<Object> New(Isolate* isolate);
V8_INLINE static Object* Cast(Value* obj);
diff --git a/src/api.cc b/src/api.cc
index e65f114edb..4302b6c604 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -9543,21 +9543,20 @@ int debug::EstimatedValueSize(Isolate* v8_isolate, v8::Local<v8::Value> value) {
return i::Handle<i::HeapObject>::cast(object)->Size();
}
-v8::MaybeLocal<v8::Array> debug::EntriesPreview(Isolate* v8_isolate,
- v8::Local<v8::Value> value,
- bool* is_key_value) {
- i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
- ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
- if (value->IsMap()) {
+v8::MaybeLocal<v8::Array> v8::Object::PreviewEntries(bool* is_key_value) {
+ if (IsMap()) {
*is_key_value = true;
- return value.As<Map>()->AsArray();
+ return Map::Cast(this)->AsArray();
}
- if (value->IsSet()) {
+ if (IsSet()) {
*is_key_value = false;
- return value.As<Set>()->AsArray();
+ return Set::Cast(this)->AsArray();
}
- i::Handle<i::Object> object = Utils::OpenHandle(*value);
+ i::Handle<i::JSReceiver> object = Utils::OpenHandle(this);
+ i::Isolate* isolate = object->GetIsolate();
+ Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
+ ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
if (object->IsJSWeakCollection()) {
*is_key_value = object->IsJSWeakMap();
return Utils::ToLocal(i::JSWeakCollection::GetEntries(
diff --git a/src/debug/debug-interface.h b/src/debug/debug-interface.h
index 01124bf7fc..2210b4e87f 100644
--- a/src/debug/debug-interface.h
+++ b/src/debug/debug-interface.h
@@ -212,10 +212,6 @@ void ResetBlackboxedStateCache(Isolate* isolate,
int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value);
-v8::MaybeLocal<v8::Array> EntriesPreview(Isolate* isolate,
- v8::Local<v8::Value> value,
- bool* is_key_value);
-
enum Builtin {
kObjectKeys,
kObjectGetPrototypeOf,
diff --git a/src/inspector/v8-debugger.cc b/src/inspector/v8-debugger.cc
index 5dee98853b..28212a1993 100644
--- a/src/inspector/v8-debugger.cc
+++ b/src/inspector/v8-debugger.cc
@@ -29,8 +29,10 @@ v8::MaybeLocal<v8::Array> collectionsEntries(v8::Local<v8::Context> context,
v8::Isolate* isolate = context->GetIsolate();
v8::Local<v8::Array> entries;
bool isKeyValue = false;
- if (!v8::debug::EntriesPreview(isolate, value, &isKeyValue).ToLocal(&entries))
+ if (!value->IsObject() ||
+ !value.As<v8::Object>()->PreviewEntries(&isKeyValue).ToLocal(&entries)) {
return v8::MaybeLocal<v8::Array>();
+ }
v8::Local<v8::Array> wrappedEntries = v8::Array::New(isolate);
CHECK(!isKeyValue || wrappedEntries->Length() % 2 == 0);

View file

@ -0,0 +1,130 @@
diff --git a/BUILD.gn b/BUILD.gn
index 494ba22f29..6071422d7d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -157,7 +157,7 @@ config("internal_config") {
include_dirs = [ "." ]
- if (is_component_build) {
+ if (is_component_build || is_electron_build) {
defines = [ "BUILDING_V8_SHARED" ]
}
}
@@ -174,6 +174,20 @@ config("libplatform_config") {
if (is_component_build) {
defines = [ "USING_V8_PLATFORM_SHARED" ]
}
+
+ # For Electron "static_library" all V8 symbols are together in one DLL.
+ # V8 targets which depend on libplatform need to be built with
+ # BUILDING_V8_PLATFORM_SHARED in order to declare its symbols as exported.
+ #
+ # Caveat:
+ # This setting applies to _all_ dependent targets, even those outside
+ # of V8! Currently there are no other targets dependent on v8_libplatform
+ # which Electron would consume, so we don't need to do more complicated tweaks
+ # but be aware of this and check that it's still the case when upgrading
+ # to newer Chromium version.
+ if (is_electron_build && !is_electron_gn_build && !is_component_build) {
+ defines = [ "BUILDING_V8_PLATFORM_SHARED" ]
+ }
}
# This config should be applied to code using the libbase.
@@ -185,6 +199,20 @@ config("libbase_config") {
if (is_android && current_toolchain != host_toolchain) {
libs += [ "log" ]
}
+
+ # For Electron "static_library" all V8 symbols are together in one DLL.
+ # V8 targets which depend on libbase need to be built with
+ # BUILDING_V8_BASE_SHARED in order to declare its symbols as exported.
+ #
+ # Caveat:
+ # This setting applies to _all_ dependent targets, even those outside
+ # of V8! Currently there are no other targets dependent on v8_libbase
+ # which Electron would consume, so we don't need to do more complicated tweaks
+ # but be aware of this and check that it's still the case when upgrading
+ # to newer Chromium version.
+ if (is_electron_build && !is_electron_gn_build && !is_component_build) {
+ defines = [ "BUILDING_V8_BASE_SHARED" ]
+ }
}
# This config should be applied to code using the libsampler.
@@ -209,7 +209,7 @@ config("libsampler_config") {
# itself.
config("external_config") {
defines = []
- if (is_component_build) {
+ if (is_component_build || (is_electron_build && !is_electron_gn_build)) {
defines += [ "USING_V8_SHARED" ]
}
if (v8_enable_v8_checks) {
@@ -2674,6 +2674,8 @@ if (current_toolchain == v8_snapshot_toolchain) {
configs = [ ":internal_config" ]
+ configs += [ "//electron/build/config:build_time_executable" ]
+
deps = [
":v8_base",
":v8_init",
@@ -2667,7 +2697,7 @@ group("v8_fuzzers") {
]
}
-if (is_component_build) {
+if (is_component_build || (is_electron_build && !is_electron_gn_build)) {
v8_component("v8") {
sources = [
"src/v8dll-main.cc",
@@ -2681,6 +2711,13 @@ if (is_component_build) {
configs = [ ":internal_config" ]
public_configs = [ ":external_config" ]
+
+ # For Electron "static_library" keep V8 as a shared library. This is only
+ # needed so that other targets in Chromium build cleanly. Electron doesn't
+ # need the DLL.
+ if (is_electron_build && !is_electron_gn_build && !is_component_build) {
+ static_component_type = "shared_library"
+ }
}
v8_component("v8_for_testing") {
diff --git a/gni/v8.gni b/gni/v8.gni
index 9a2bb3dff4..53be2017c7 100644
--- a/gni/v8.gni
+++ b/gni/v8.gni
@@ -164,6 +164,16 @@ template("v8_executable") {
template("v8_component") {
component(target_name) {
+ # If this is a non-component build, but this target forces itself to be
+ # a shared library, we must reset the default configs that were applied
+ # (see the set_defaults("component") statement in BUILDCONFIG.gn)
+ # and assign those for shared libraries.
+ if (defined(invoker.static_component_type) &&
+ invoker.static_component_type == "shared_library") {
+ configs = []
+ configs = default_shared_library_configs
+ }
+
forward_variables_from(invoker, "*", [ "configs" ])
configs += invoker.configs
configs -= v8_remove_configs
diff --git a/src/inspector/BUILD.gn b/src/inspector/BUILD.gn
index 699b1bcbd4..11fc31d851 100644
--- a/src/inspector/BUILD.gn
+++ b/src/inspector/BUILD.gn
@@ -79,7 +79,7 @@ action("inspector_injected_script") {
config("inspector_config") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
- if (is_component_build) {
+ if (is_component_build || is_electron_build) {
defines = [ "BUILDING_V8_SHARED" ]
}
}

View file

@ -0,0 +1,12 @@
diff --git a/src/log.cc b/src/log.cc
index 903cc8e2e6..ce917b0be1 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -327,6 +327,7 @@ void PerfBasicLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
const char* name, int length) {
if (FLAG_perf_basic_prof_only_functions &&
(code->kind() != AbstractCode::INTERPRETED_FUNCTION &&
+ code->kind() != AbstractCode::BUILTIN &&
code->kind() != AbstractCode::OPTIMIZED_FUNCTION)) {
return;
}

View file

@ -0,0 +1,300 @@
diff --git a/src/js/intl.js b/src/js/intl.js
index 53fbe1f947..3c7112716c 100644
--- a/src/js/intl.js
+++ b/src/js/intl.js
@@ -152,18 +152,11 @@ var AVAILABLE_LOCALES = {
*/
var DEFAULT_ICU_LOCALE = UNDEFINED;
-function GetDefaultICULocaleJS(service) {
+function GetDefaultICULocaleJS() {
if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) {
DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
}
- // Check that this is a valid default for this service,
- // otherwise fall back to "und"
- // TODO(littledan,jshin): AvailableLocalesOf sometimes excludes locales
- // which don't require tailoring, but work fine with root data. Look into
- // exposing this fact in ICU or the way Chrome bundles data.
- return (IS_UNDEFINED(service) ||
- HAS_OWN_PROPERTY(getAvailableLocalesOf(service), DEFAULT_ICU_LOCALE))
- ? DEFAULT_ICU_LOCALE : "und";
+ return DEFAULT_ICU_LOCALE;
}
/**
@@ -434,6 +427,48 @@ function resolveLocale(service, requestedLocales, options) {
}
+/**
+ * Look up the longest non-empty prefix of |locale| that is an element of
+ * |availableLocales|. Returns undefined when the |locale| is completely
+ * unsupported by |availableLocales|.
+ */
+function bestAvailableLocale(availableLocales, locale) {
+ do {
+ if (!IS_UNDEFINED(availableLocales[locale])) {
+ return locale;
+ }
+ // Truncate locale if possible.
+ var pos = %StringLastIndexOf(locale, '-');
+ if (pos === -1) {
+ break;
+ }
+ locale = %_Call(StringSubstring, locale, 0, pos);
+ } while (true);
+
+ return UNDEFINED;
+}
+
+
+/**
+ * Try to match any mutation of |requestedLocale| against |availableLocales|.
+ */
+function attemptSingleLookup(availableLocales, requestedLocale) {
+ // Remove all extensions.
+ var noExtensionsLocale = %RegExpInternalReplace(
+ GetAnyExtensionRE(), requestedLocale, '');
+ var availableLocale = bestAvailableLocale(
+ availableLocales, requestedLocale);
+ if (!IS_UNDEFINED(availableLocale)) {
+ // Return the resolved locale and extension.
+ var extensionMatch = %regexp_internal_match(
+ GetUnicodeExtensionRE(), requestedLocale);
+ var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0];
+ return {locale: availableLocale, extension: extension};
+ }
+ return UNDEFINED;
+}
+
+
/**
* Returns best matched supported locale and extension info using basic
* lookup algorithm.
@@ -446,31 +481,25 @@ function lookupMatcher(service, requestedLocales) {
var availableLocales = getAvailableLocalesOf(service);
for (var i = 0; i < requestedLocales.length; ++i) {
- // Remove all extensions.
- var locale = %RegExpInternalReplace(
- GetAnyExtensionRE(), requestedLocales[i], '');
- do {
- if (!IS_UNDEFINED(availableLocales[locale])) {
- // Return the resolved locale and extension.
- var extensionMatch = %regexp_internal_match(
- GetUnicodeExtensionRE(), requestedLocales[i]);
- var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0];
- return {locale: locale, extension: extension, position: i};
- }
- // Truncate locale if possible.
- var pos = %StringLastIndexOf(locale, '-');
- if (pos === -1) {
- break;
- }
- locale = %_Call(StringSubstring, locale, 0, pos);
- } while (true);
+ var result = attemptSingleLookup(availableLocales, requestedLocales[i]);
+ if (!IS_UNDEFINED(result)) {
+ return result;
+ }
+ }
+
+ var defLocale = GetDefaultICULocaleJS();
+
+ // While ECMA-402 returns defLocale directly, we have to check if it is
+ // supported, as such support is not guaranteed.
+ var result = attemptSingleLookup(availableLocales, defLocale);
+ if (!IS_UNDEFINED(result)) {
+ return result;
}
// Didn't find a match, return default.
return {
- locale: GetDefaultICULocaleJS(service),
- extension: '',
- position: -1
+ locale: 'und',
+ extension: ''
};
}
diff --git a/test/intl/assert.js b/test/intl/assert.js
index d8cc85849f..c11e7c0bbf 100644
--- a/test/intl/assert.js
+++ b/test/intl/assert.js
@@ -132,6 +132,16 @@ function assertFalse(value, user_message = '') {
}
+/**
+ * Throws if value is null.
+ */
+function assertNotNull(value, user_message = '') {
+ if (value === null) {
+ fail("not null", value, user_message);
+ }
+}
+
+
/**
* Runs code() and asserts that it throws the specified exception.
*/
@@ -189,3 +199,34 @@ function assertInstanceof(obj, type) {
(actualTypeName ? ' but of < ' + actualTypeName + '>' : ''));
}
}
+
+
+/**
+ * Split a BCP 47 language tag into locale and extension.
+ */
+function splitLanguageTag(tag) {
+ var extRe = /(-[0-9A-Za-z](-[0-9A-Za-z]{2,8})+)+$/;
+ var match = %regexp_internal_match(extRe, tag);
+ if (match) {
+ return { locale: tag.slice(0, match.index), extension: match[0] };
+ }
+
+ return { locale: tag, extension: '' };
+}
+
+
+/**
+ * Throw if |parent| is not a more general language tag of |child|, nor |child|
+ * itself, per BCP 47 rules.
+ */
+function assertLanguageTag(child, parent) {
+ var childSplit = splitLanguageTag(child);
+ var parentSplit = splitLanguageTag(parent);
+
+ // Do not compare extensions at this moment, as %GetDefaultICULocale()
+ // doesn't always output something we support.
+ if (childSplit.locale !== parentSplit.locale &&
+ !childSplit.locale.startsWith(parentSplit.locale + '-')) {
+ fail(child, parent, 'language tag comparison');
+ }
+}
diff --git a/test/intl/break-iterator/default-locale.js b/test/intl/break-iterator/default-locale.js
index d8d5aeadb2..e1a42a100a 100644
--- a/test/intl/break-iterator/default-locale.js
+++ b/test/intl/break-iterator/default-locale.js
@@ -37,8 +37,8 @@ assertFalse(options.locale === 'und');
assertFalse(options.locale === '');
assertFalse(options.locale === undefined);
-// Then check for equality.
-assertEquals(options.locale, %GetDefaultICULocale());
+// Then check for legitimacy.
+assertLanguageTag(%GetDefaultICULocale(), options.locale);
var iteratorNone = new Intl.v8BreakIterator();
assertEquals(options.locale, iteratorNone.resolvedOptions().locale);
diff --git a/test/intl/break-iterator/wellformed-unsupported-locale.js b/test/intl/break-iterator/wellformed-unsupported-locale.js
index 5ac8fbcd41..ffa44aef08 100644
--- a/test/intl/break-iterator/wellformed-unsupported-locale.js
+++ b/test/intl/break-iterator/wellformed-unsupported-locale.js
@@ -29,4 +29,4 @@
var iterator = Intl.v8BreakIterator(['xx']);
-assertEquals(iterator.resolvedOptions().locale, %GetDefaultICULocale());
+assertLanguageTag(%GetDefaultICULocale(), iterator.resolvedOptions().locale);
diff --git a/test/intl/collator/default-locale.js b/test/intl/collator/default-locale.js
index db9b1e7330..5fc6ff4665 100644
--- a/test/intl/collator/default-locale.js
+++ b/test/intl/collator/default-locale.js
@@ -37,8 +37,8 @@ assertFalse(options.locale === 'und');
assertFalse(options.locale === '');
assertFalse(options.locale === undefined);
-// Then check for equality.
-assertEquals(options.locale, %GetDefaultICULocale());
+// Then check for legitimacy.
+assertLanguageTag(%GetDefaultICULocale(), options.locale);
var collatorNone = new Intl.Collator();
assertEquals(options.locale, collatorNone.resolvedOptions().locale);
@@ -48,5 +48,8 @@ var collatorBraket = new Intl.Collator({});
assertEquals(options.locale, collatorBraket.resolvedOptions().locale);
var collatorWithOptions = new Intl.Collator(undefined, {usage: 'search'});
-assertEquals(%GetDefaultICULocale() + '-u-co-search',
- collatorWithOptions.resolvedOptions().locale);
+assertLanguageTag(%GetDefaultICULocale(),
+ collatorWithOptions.resolvedOptions().locale);
+assertNotNull(
+ %regexp_internal_match(/-u(-[a-zA-Z]+-[a-zA-Z]+)*-co-search/,
+ collatorWithOptions.resolvedOptions().locale));
diff --git a/test/intl/collator/wellformed-unsupported-locale.js b/test/intl/collator/wellformed-unsupported-locale.js
index 3963d47a61..ad89e3e220 100644
--- a/test/intl/collator/wellformed-unsupported-locale.js
+++ b/test/intl/collator/wellformed-unsupported-locale.js
@@ -29,4 +29,4 @@
var collator = Intl.Collator(['xx']);
-assertEquals(collator.resolvedOptions().locale, %GetDefaultICULocale());
+assertLanguageTag(%GetDefaultICULocale(), collator.resolvedOptions().locale);
diff --git a/test/intl/date-format/default-locale.js b/test/intl/date-format/default-locale.js
index 8e9b7fcec3..2d79e895b5 100644
--- a/test/intl/date-format/default-locale.js
+++ b/test/intl/date-format/default-locale.js
@@ -37,8 +37,8 @@ assertFalse(options.locale === 'und');
assertFalse(options.locale === '');
assertFalse(options.locale === undefined);
-// Then check for equality.
-assertEquals(options.locale, %GetDefaultICULocale());
+// Then check for legitimacy.
+assertLanguageTag(%GetDefaultICULocale(), options.locale);
var dtfNone = new Intl.DateTimeFormat();
assertEquals(options.locale, dtfNone.resolvedOptions().locale);
diff --git a/test/intl/date-format/wellformed-unsupported-locale.js b/test/intl/date-format/wellformed-unsupported-locale.js
index 6f063abbd1..b812164832 100644
--- a/test/intl/date-format/wellformed-unsupported-locale.js
+++ b/test/intl/date-format/wellformed-unsupported-locale.js
@@ -29,4 +29,4 @@
var dtf = Intl.DateTimeFormat(['xx']);
-assertEquals(dtf.resolvedOptions().locale, %GetDefaultICULocale());
+assertLanguageTag(%GetDefaultICULocale(), dtf.resolvedOptions().locale);
diff --git a/test/intl/number-format/default-locale.js b/test/intl/number-format/default-locale.js
index cd67ba724f..a24aec2333 100644
--- a/test/intl/number-format/default-locale.js
+++ b/test/intl/number-format/default-locale.js
@@ -37,8 +37,8 @@ assertFalse(options.locale === 'und');
assertFalse(options.locale === '');
assertFalse(options.locale === undefined);
-// Then check for equality.
-assertEquals(options.locale, %GetDefaultICULocale());
+// Then check for legitimacy.
+assertLanguageTag(%GetDefaultICULocale(), options.locale);
var nfNone = new Intl.NumberFormat();
assertEquals(options.locale, nfNone.resolvedOptions().locale);
diff --git a/test/intl/number-format/wellformed-unsupported-locale.js b/test/intl/number-format/wellformed-unsupported-locale.js
index 195eba4c19..c51753928e 100644
--- a/test/intl/number-format/wellformed-unsupported-locale.js
+++ b/test/intl/number-format/wellformed-unsupported-locale.js
@@ -29,4 +29,4 @@
var nf = Intl.NumberFormat(['xx']);
-assertEquals(nf.resolvedOptions().locale, %GetDefaultICULocale());
+assertLanguageTag(%GetDefaultICULocale(), nf.resolvedOptions().locale);
diff --git a/test/mjsunit/regress/regress-6288.js b/test/mjsunit/regress/regress-6288.js
index 337af54c1a..5f550c31c8 100644
--- a/test/mjsunit/regress/regress-6288.js
+++ b/test/mjsunit/regress/regress-6288.js
@@ -8,6 +8,6 @@
// DateTimeFormat but not Collation
if (this.Intl) {
- assertEquals('und', Intl.Collator().resolvedOptions().locale);
+ assertEquals('pt', Intl.Collator().resolvedOptions().locale);
assertEquals('pt-BR', Intl.DateTimeFormat().resolvedOptions().locale);
}

View file

@ -0,0 +1,30 @@
diff --git a/src/api.cc b/src/api.cc
index b46d376837..a97b38d00a 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -10217,6 +10217,10 @@ const char* CodeEvent::GetCodeEventTypeName(CodeEventType code_event_type) {
CODE_EVENTS_LIST(V)
#undef V
}
+ // The execution should never pass here
+ UNREACHABLE();
+ // NOTE(mmarchini): Workaround to fix a compiler failure on GCC 4.9
+ return "Unknown";
}
CodeEventHandler::CodeEventHandler(Isolate* isolate) {
diff --git a/src/log.cc b/src/log.cc
index d1673715e5..f70acbd54d 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -59,6 +59,10 @@ static v8::CodeEventType GetCodeEventTypeForTag(
TAGS_LIST(V)
#undef V
}
+ // The execution should never pass here
+ UNREACHABLE();
+ // NOTE(mmarchini): Workaround to fix a compiler failure on GCC 4.9
+ return v8::CodeEventType::kUnknownType;
}
#define CALL_CODE_EVENT_HANDLER(Call) \
if (listener_) { \

View file

@ -0,0 +1,225 @@
diff --git a/include/v8.h b/include/v8.h
index 29566f4303..07a500f7ff 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1578,6 +1578,9 @@ class V8_EXPORT ScriptCompiler {
* This will return nullptr if the script cannot be serialized. The
* CachedData returned by this function should be owned by the caller.
*/
+ static CachedData* CreateCodeCache(Local<UnboundScript> unbound_script);
+
+ // Deprecated.
static CachedData* CreateCodeCache(Local<UnboundScript> unbound_script,
Local<String> source);
@@ -1587,6 +1590,9 @@ class V8_EXPORT ScriptCompiler {
* This will return nullptr if the script cannot be serialized. The
* CachedData returned by this function should be owned by the caller.
*/
+ static CachedData* CreateCodeCacheForFunction(Local<Function> function);
+
+ // Deprecated.
static CachedData* CreateCodeCacheForFunction(Local<Function> function,
Local<String> source);
diff --git a/src/api.cc b/src/api.cc
index 27e7598bfa..61b1be1401 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2628,21 +2628,29 @@ uint32_t ScriptCompiler::CachedDataVersionTag() {
ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
Local<UnboundScript> unbound_script, Local<String> source) {
+ return CreateCodeCache(unbound_script);
+}
+
+ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
+ Local<UnboundScript> unbound_script) {
i::Handle<i::SharedFunctionInfo> shared =
i::Handle<i::SharedFunctionInfo>::cast(
Utils::OpenHandle(*unbound_script));
- i::Handle<i::String> source_str = Utils::OpenHandle(*source);
DCHECK(shared->is_toplevel());
- return i::CodeSerializer::Serialize(shared, source_str);
+ return i::CodeSerializer::Serialize(shared);
}
ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCacheForFunction(
Local<Function> function, Local<String> source) {
+ return CreateCodeCacheForFunction(function);
+}
+
+ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCacheForFunction(
+ Local<Function> function) {
i::Handle<i::SharedFunctionInfo> shared(
i::Handle<i::JSFunction>::cast(Utils::OpenHandle(*function))->shared());
- i::Handle<i::String> source_str = Utils::OpenHandle(*source);
CHECK(shared->is_wrapped());
- return i::CodeSerializer::Serialize(shared, source_str);
+ return i::CodeSerializer::Serialize(shared);
}
MaybeLocal<Script> Script::Compile(Local<Context> context, Local<String> source,
diff --git a/src/d8.cc b/src/d8.cc
index b338dfbb2d..e6ba022795 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -636,7 +636,7 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
ShellOptions::CodeCacheOptions::kProduceCache) {
// Serialize and store it in memory for the next execution.
ScriptCompiler::CachedData* cached_data =
- ScriptCompiler::CreateCodeCache(script->GetUnboundScript(), source);
+ ScriptCompiler::CreateCodeCache(script->GetUnboundScript());
StoreInCodeCache(isolate, source, cached_data);
delete cached_data;
}
@@ -645,7 +645,7 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
ShellOptions::CodeCacheOptions::kProduceCacheAfterExecute) {
// Serialize and store it in memory for the next execution.
ScriptCompiler::CachedData* cached_data =
- ScriptCompiler::CreateCodeCache(script->GetUnboundScript(), source);
+ ScriptCompiler::CreateCodeCache(script->GetUnboundScript());
StoreInCodeCache(isolate, source, cached_data);
delete cached_data;
}
diff --git a/src/snapshot/code-serializer.cc b/src/snapshot/code-serializer.cc
index 2697e9dce4..823d8dc9af 100644
--- a/src/snapshot/code-serializer.cc
+++ b/src/snapshot/code-serializer.cc
@@ -32,7 +32,7 @@ ScriptData::ScriptData(const byte* data, int length)
// static
ScriptCompiler::CachedData* CodeSerializer::Serialize(
- Handle<SharedFunctionInfo> info, Handle<String> source) {
+ Handle<SharedFunctionInfo> info) {
Isolate* isolate = info->GetIsolate();
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
HistogramTimerScope histogram_timer(isolate->counters()->compile_serialize());
@@ -45,8 +45,7 @@ ScriptCompiler::CachedData* CodeSerializer::Serialize(
Handle<Script> script(Script::cast(info->script()), isolate);
if (FLAG_trace_serializer) {
PrintF("[Serializing from");
- Object* script = info->script();
- Script::cast(script)->name()->ShortPrint();
+ script->name()->ShortPrint();
PrintF("]\n");
}
// TODO(7110): Enable serialization of Asm modules once the AsmWasmData is
@@ -55,10 +54,11 @@ ScriptCompiler::CachedData* CodeSerializer::Serialize(
if (isolate->debug()->is_loaded()) return nullptr;
// Serialize code object.
+ Handle<String> source(String::cast(script->source()), isolate);
CodeSerializer cs(isolate, SerializedCodeData::SourceHash(source));
DisallowHeapAllocation no_gc;
cs.reference_map()->AddAttachedReference(*source);
- ScriptData* script_data = cs.Serialize(info);
+ ScriptData* script_data = cs.SerializeSharedFunctionInfo(info);
if (FLAG_profile_deserialization) {
double ms = timer.Elapsed().InMillisecondsF();
@@ -75,11 +75,12 @@ ScriptCompiler::CachedData* CodeSerializer::Serialize(
return result;
}
-ScriptData* CodeSerializer::Serialize(Handle<HeapObject> obj) {
+ScriptData* CodeSerializer::SerializeSharedFunctionInfo(
+ Handle<SharedFunctionInfo> info) {
DisallowHeapAllocation no_gc;
VisitRootPointer(Root::kHandleScope, nullptr,
- Handle<Object>::cast(obj).location());
+ Handle<Object>::cast(info).location());
SerializeDeferredObjects();
Pad();
diff --git a/src/snapshot/code-serializer.h b/src/snapshot/code-serializer.h
index 8e97f47f2f..f6b51bf9b1 100644
--- a/src/snapshot/code-serializer.h
+++ b/src/snapshot/code-serializer.h
@@ -45,10 +45,9 @@ class ScriptData {
class CodeSerializer : public Serializer<> {
public:
- static ScriptCompiler::CachedData* Serialize(Handle<SharedFunctionInfo> info,
- Handle<String> source);
+ static ScriptCompiler::CachedData* Serialize(Handle<SharedFunctionInfo> info);
- ScriptData* Serialize(Handle<HeapObject> obj);
+ ScriptData* SerializeSharedFunctionInfo(Handle<SharedFunctionInfo> info);
V8_WARN_UNUSED_RESULT static MaybeHandle<SharedFunctionInfo> Deserialize(
Isolate* isolate, ScriptData* cached_data, Handle<String> source);
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index f242262cf0..fbcc12190e 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -25428,8 +25428,7 @@ TEST(CodeCache) {
v8::ScriptCompiler::kNoCompileOptions;
v8::Local<v8::Script> script =
v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
- cache = v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript(),
- source_string);
+ cache = v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript());
}
isolate1->Dispose();
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 370791f6c2..817561c68a 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -1240,8 +1240,7 @@ static Handle<SharedFunctionInfo> CompileScriptAndProduceCache(
NOT_NATIVES_CODE)
.ToHandleChecked();
std::unique_ptr<ScriptCompiler::CachedData> cached_data(
- ScriptCompiler::CreateCodeCache(ToApiHandle<UnboundScript>(sfi),
- Utils::ToLocal(source)));
+ ScriptCompiler::CreateCodeCache(ToApiHandle<UnboundScript>(sfi)));
uint8_t* buffer = NewArray<uint8_t>(cached_data->length);
MemCopy(buffer, cached_data->data, cached_data->length);
*script_data = new i::ScriptData(buffer, cached_data->length);
@@ -1895,7 +1894,7 @@ v8::ScriptCompiler::CachedData* CompileRunAndProduceCache(
.ToLocalChecked();
if (cacheType != CodeCacheType::kAfterExecute) {
- cache = ScriptCompiler::CreateCodeCache(script, source_str);
+ cache = ScriptCompiler::CreateCodeCache(script);
}
v8::Local<v8::Value> result = script->BindToCurrentContext()
@@ -1907,7 +1906,7 @@ v8::ScriptCompiler::CachedData* CompileRunAndProduceCache(
.FromJust());
if (cacheType == CodeCacheType::kAfterExecute) {
- cache = ScriptCompiler::CreateCodeCache(script, source_str);
+ cache = ScriptCompiler::CreateCodeCache(script);
}
CHECK(cache);
}
@@ -2153,7 +2152,7 @@ TEST(CodeSerializerWithHarmonyScoping) {
v8::ScriptCompiler::CompileUnboundScript(
isolate1, &source, v8::ScriptCompiler::kNoCompileOptions)
.ToLocalChecked();
- cache = v8::ScriptCompiler::CreateCodeCache(script, source_str);
+ cache = v8::ScriptCompiler::CreateCodeCache(script);
CHECK(cache);
v8::Local<v8::Value> result = script->BindToCurrentContext()
@@ -2218,7 +2217,7 @@ TEST(Regress503552) {
heap::SimulateIncrementalMarking(isolate->heap());
v8::ScriptCompiler::CachedData* cache_data =
- CodeSerializer::Serialize(shared, source);
+ CodeSerializer::Serialize(shared);
delete cache_data;
}
@@ -3447,7 +3446,7 @@ TEST(CachedCompileFunctionInContext) {
env.local(), &script_source, 1, &arg_str, 0, nullptr,
v8::ScriptCompiler::kEagerCompile)
.ToLocalChecked();
- cache = v8::ScriptCompiler::CreateCodeCacheForFunction(fun, source);
+ cache = v8::ScriptCompiler::CreateCodeCacheForFunction(fun);
}
{

View file

@ -0,0 +1,153 @@
diff --git a/src/log.cc b/src/log.cc
index e50b00a320..832ef7519d 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -2023,7 +2023,7 @@ void ExistingCodeLogger::LogCodeObject(Object* object) {
break;
case AbstractCode::BUILTIN:
if (Code::cast(object)->is_interpreter_trampoline_builtin() &&
- Code::cast(object) ==
+ Code::cast(object) !=
*BUILTIN_CODE(isolate_, InterpreterEntryTrampoline)) {
return;
}
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index c7864034c9..767541d4a3 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -36,6 +36,9 @@
#include <unordered_set>
#include <vector>
+// The C++ style guide recommends using <re2> instead of <regex>. However, the
+// former isn't available in V8.
+#include <regex> // NOLINT(build/c++11)
#include "src/api.h"
#include "src/log-utils.h"
#include "src/log.h"
@@ -257,30 +260,41 @@ class TestCodeEventHandler : public v8::CodeEventHandler {
explicit TestCodeEventHandler(v8::Isolate* isolate)
: v8::CodeEventHandler(isolate) {}
- const char* FindLine(const char* prefix, const char* suffix = nullptr,
- const char* start = nullptr) {
- if (!log_.length()) return NULL;
- const char* c_log = log_.c_str();
- if (start == nullptr) start = c_log;
- const char* end = c_log + log_.length();
- return FindLogLine(start, end, prefix, suffix);
+ size_t CountLines(std::string prefix, std::string suffix = std::string()) {
+ if (!log_.length()) return 0;
+
+ std::regex expression("(^|\\n)" + prefix + ".*" + suffix + "(?=\\n|$)");
+
+ size_t match_count(std::distance(
+ std::sregex_iterator(log_.begin(), log_.end(), expression),
+ std::sregex_iterator()));
+
+ return match_count;
}
void Handle(v8::CodeEvent* code_event) override {
- const char* code_type =
- v8::CodeEvent::GetCodeEventTypeName(code_event->GetCodeType());
- char function_name[1000];
- strncpy(function_name, code_type, 1000);
- function_name[strlen(code_type)] = ' ';
- code_event->GetFunctionName()->WriteUtf8(
- function_name + strlen(code_type) + 1, 1000);
- function_name[strlen(function_name) + 1] = '\0';
- function_name[strlen(function_name)] = '\n';
-
- log_ += std::string(function_name);
+ std::string log_line = "";
+ log_line += v8::CodeEvent::GetCodeEventTypeName(code_event->GetCodeType());
+ log_line += " ";
+ log_line += FormatName(code_event);
+ log_line += "\n";
+ log_ += log_line;
}
private:
+ std::string FormatName(v8::CodeEvent* code_event) {
+ std::string name = std::string(code_event->GetComment());
+ if (name.empty()) {
+ v8::Local<v8::String> functionName = code_event->GetFunctionName();
+ std::string buffer(functionName->Utf8Length() + 1, 0);
+ functionName->WriteUtf8(&buffer[0], functionName->Utf8Length() + 1);
+ // Sanitize name, removing unwanted \0 resulted from WriteUtf8
+ name = std::string(buffer.c_str());
+ }
+
+ return name;
+ }
+
std::string log_;
};
@@ -854,21 +868,24 @@ TEST(ExternalCodeEventListener) {
"testCodeEventListenerBeforeStart('1', 1);";
CompileRun(source_text_before_start);
- CHECK_NULL(code_event_handler.FindLine("LazyCompile",
- "testCodeEventListenerBeforeStart"));
+ CHECK_EQ(code_event_handler.CountLines("LazyCompile",
+ "testCodeEventListenerBeforeStart"),
+ 0);
code_event_handler.Enable();
- CHECK_NOT_NULL(code_event_handler.FindLine(
- "LazyCompile", "testCodeEventListenerBeforeStart"));
+ CHECK_GE(code_event_handler.CountLines("LazyCompile",
+ "testCodeEventListenerBeforeStart"),
+ 1);
const char* source_text_after_start =
"function testCodeEventListenerAfterStart(a,b) { return a + b };"
"testCodeEventListenerAfterStart('1', 1);";
CompileRun(source_text_after_start);
- CHECK_NOT_NULL(code_event_handler.FindLine(
- "LazyCompile", "testCodeEventListenerAfterStart"));
+ CHECK_GE(code_event_handler.CountLines("LazyCompile",
+ "testCodeEventListenerAfterStart"),
+ 1);
context->Exit();
}
@@ -897,21 +914,28 @@ TEST(ExternalCodeEventListenerWithInterpretedFramesNativeStack) {
"testCodeEventListenerBeforeStart('1', 1);";
CompileRun(source_text_before_start);
- CHECK_NULL(code_event_handler.FindLine("InterpretedFunction",
- "testCodeEventListenerBeforeStart"));
+ CHECK_EQ(code_event_handler.CountLines("InterpretedFunction",
+ "testCodeEventListenerBeforeStart"),
+ 0);
code_event_handler.Enable();
- CHECK_NOT_NULL(code_event_handler.FindLine(
- "InterpretedFunction", "testCodeEventListenerBeforeStart"));
+ CHECK_GE(code_event_handler.CountLines("InterpretedFunction",
+ "testCodeEventListenerBeforeStart"),
+ 1);
const char* source_text_after_start =
"function testCodeEventListenerAfterStart(a,b) { return a + b };"
"testCodeEventListenerAfterStart('1', 1);";
CompileRun(source_text_after_start);
- CHECK_NOT_NULL(code_event_handler.FindLine(
- "InterpretedFunction", "testCodeEventListenerAfterStart"));
+ CHECK_GE(code_event_handler.CountLines("InterpretedFunction",
+ "testCodeEventListenerAfterStart"),
+ 1);
+
+ CHECK_EQ(
+ code_event_handler.CountLines("Builtin", "InterpreterEntryTrampoline"),
+ 1);
context->Exit();
}

View file

@ -0,0 +1,183 @@
diff --git a/src/log.cc b/src/log.cc
index 563fe3c5f0..edd883976d 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -2011,10 +2011,10 @@ FILE* Logger::TearDown() {
}
void ExistingCodeLogger::LogCodeObject(Object* object) {
- AbstractCode* code_object = AbstractCode::cast(object);
+ AbstractCode* abstract_code = AbstractCode::cast(object);
CodeEventListener::LogEventsAndTags tag = CodeEventListener::STUB_TAG;
const char* description = "Unknown code from before profiling";
- switch (code_object->kind()) {
+ switch (abstract_code->kind()) {
case AbstractCode::INTERPRETED_FUNCTION:
case AbstractCode::OPTIMIZED_FUNCTION:
return; // We log this later using LogCompiledFunctions.
@@ -2022,7 +2022,7 @@ void ExistingCodeLogger::LogCodeObject(Object* object) {
return; // We log it later by walking the dispatch table.
case AbstractCode::STUB:
description =
- CodeStub::MajorName(CodeStub::GetMajorKey(code_object->GetCode()));
+ CodeStub::MajorName(CodeStub::GetMajorKey(abstract_code->GetCode()));
if (description == nullptr) description = "A stub from before profiling";
tag = CodeEventListener::STUB_TAG;
break;
@@ -2031,8 +2031,13 @@ void ExistingCodeLogger::LogCodeObject(Object* object) {
tag = CodeEventListener::REG_EXP_TAG;
break;
case AbstractCode::BUILTIN:
+ if (Code::cast(object)->is_interpreter_trampoline_builtin() &&
+ Code::cast(object) ==
+ *BUILTIN_CODE(isolate_, InterpreterEntryTrampoline)) {
+ return;
+ }
description =
- isolate_->builtins()->name(code_object->GetCode()->builtin_index());
+ isolate_->builtins()->name(abstract_code->GetCode()->builtin_index());
tag = CodeEventListener::BUILTIN_TAG;
break;
case AbstractCode::WASM_FUNCTION:
@@ -2058,7 +2063,7 @@ void ExistingCodeLogger::LogCodeObject(Object* object) {
case AbstractCode::NUMBER_OF_KINDS:
UNIMPLEMENTED();
}
- CALL_CODE_EVENT_HANDLER(CodeCreateEvent(tag, code_object, description))
+ CALL_CODE_EVENT_HANDLER(CodeCreateEvent(tag, abstract_code, description))
}
void ExistingCodeLogger::LogCodeObjects() {
@@ -2084,6 +2089,12 @@ void ExistingCodeLogger::LogCompiledFunctions() {
// During iteration, there can be heap allocation due to
// GetScriptLineNumber call.
for (int i = 0; i < compiled_funcs_count; ++i) {
+ if (sfis[i]->function_data()->IsInterpreterData()) {
+ LogExistingFunction(sfis[i],
+ Handle<AbstractCode>(AbstractCode::cast(
+ sfis[i]->InterpreterTrampoline())),
+ CodeEventListener::INTERPRETED_FUNCTION_TAG);
+ }
if (code_objects[i].is_identical_to(BUILTIN_CODE(isolate_, CompileLazy)))
continue;
LogExistingFunction(sfis[i], code_objects[i]);
@@ -2128,8 +2139,9 @@ void ExistingCodeLogger::LogBytecodeHandlers() {
}
}
-void ExistingCodeLogger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
- Handle<AbstractCode> code) {
+void ExistingCodeLogger::LogExistingFunction(
+ Handle<SharedFunctionInfo> shared, Handle<AbstractCode> code,
+ CodeEventListener::LogEventsAndTags tag) {
if (shared->script()->IsScript()) {
Handle<Script> script(Script::cast(shared->script()));
int line_num = Script::GetLineNumber(script, shared->StartPosition()) + 1;
@@ -2139,9 +2151,8 @@ void ExistingCodeLogger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
Handle<String> script_name(String::cast(script->name()));
if (line_num > 0) {
CALL_CODE_EVENT_HANDLER(
- CodeCreateEvent(Logger::ToNativeByScript(
- CodeEventListener::LAZY_COMPILE_TAG, *script),
- *code, *shared, *script_name, line_num, column_num))
+ CodeCreateEvent(Logger::ToNativeByScript(tag, *script), *code,
+ *shared, *script_name, line_num, column_num))
} else {
// Can't distinguish eval and script here, so always use Script.
CALL_CODE_EVENT_HANDLER(CodeCreateEvent(
@@ -2149,11 +2160,9 @@ void ExistingCodeLogger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
*code, *shared, *script_name))
}
} else {
- CALL_CODE_EVENT_HANDLER(
- CodeCreateEvent(Logger::ToNativeByScript(
- CodeEventListener::LAZY_COMPILE_TAG, *script),
- *code, *shared, isolate_->heap()->empty_string(),
- line_num, column_num))
+ CALL_CODE_EVENT_HANDLER(CodeCreateEvent(
+ Logger::ToNativeByScript(tag, *script), *code, *shared,
+ isolate_->heap()->empty_string(), line_num, column_num))
}
} else if (shared->IsApiFunction()) {
// API function.
@@ -2169,9 +2178,8 @@ void ExistingCodeLogger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
CALL_CODE_EVENT_HANDLER(CallbackEvent(shared->DebugName(), entry_point))
}
} else {
- CALL_CODE_EVENT_HANDLER(CodeCreateEvent(CodeEventListener::LAZY_COMPILE_TAG,
- *code, *shared,
- isolate_->heap()->empty_string()))
+ CALL_CODE_EVENT_HANDLER(
+ CodeCreateEvent(tag, *code, *shared, isolate_->heap()->empty_string()))
}
}
diff --git a/src/log.h b/src/log.h
index 738aef4d73..ad254097e6 100644
--- a/src/log.h
+++ b/src/log.h
@@ -109,7 +109,9 @@ class ExistingCodeLogger {
void LogCompiledFunctions();
void LogExistingFunction(Handle<SharedFunctionInfo> shared,
- Handle<AbstractCode> code);
+ Handle<AbstractCode> code,
+ CodeEventListener::LogEventsAndTags tag =
+ CodeEventListener::LAZY_COMPILE_TAG);
void LogCodeObject(Object* object);
void LogBytecodeHandler(interpreter::Bytecode bytecode,
interpreter::OperandScale operand_scale, Code* code);
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 97071a63f5..c7864034c9 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -875,6 +875,49 @@ TEST(ExternalCodeEventListener) {
isolate->Dispose();
}
+TEST(ExternalCodeEventListenerWithInterpretedFramesNativeStack) {
+ i::FLAG_log = false;
+ i::FLAG_prof = false;
+ i::FLAG_interpreted_frames_native_stack = true;
+
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+ v8::Isolate* isolate = v8::Isolate::New(create_params);
+
+ {
+ v8::HandleScope scope(isolate);
+ v8::Isolate::Scope isolate_scope(isolate);
+ v8::Local<v8::Context> context = v8::Context::New(isolate);
+ context->Enter();
+
+ TestCodeEventHandler code_event_handler(isolate);
+
+ const char* source_text_before_start =
+ "function testCodeEventListenerBeforeStart(a,b) { return a + b };"
+ "testCodeEventListenerBeforeStart('1', 1);";
+ CompileRun(source_text_before_start);
+
+ CHECK_NULL(code_event_handler.FindLine("InterpretedFunction",
+ "testCodeEventListenerBeforeStart"));
+
+ code_event_handler.Enable();
+
+ CHECK_NOT_NULL(code_event_handler.FindLine(
+ "InterpretedFunction", "testCodeEventListenerBeforeStart"));
+
+ const char* source_text_after_start =
+ "function testCodeEventListenerAfterStart(a,b) { return a + b };"
+ "testCodeEventListenerAfterStart('1', 1);";
+ CompileRun(source_text_after_start);
+
+ CHECK_NOT_NULL(code_event_handler.FindLine(
+ "InterpretedFunction", "testCodeEventListenerAfterStart"));
+
+ context->Exit();
+ }
+ isolate->Dispose();
+}
+
TEST(TraceMaps) {
SETUP_FLAGS();
i::FLAG_trace_maps = true;

View file

@ -0,0 +1,30 @@
diff --git a/src/api.cc b/src/api.cc
index 8531cd5c05..47254c9f5c 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -8598,7 +8604,7 @@ void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
void Isolate::RunMicrotasks() {
- DCHECK_NE(MicrotasksPolicy::kScoped, GetMicrotasksPolicy());
+ // DCHECK_NE(MicrotasksPolicy::kScoped, GetMicrotasksPolicy());
reinterpret_cast<i::Isolate*>(this)->RunMicrotasks();
}
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 62a5856f34..c59dfad2c8 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -5963,9 +5963,9 @@ void Heap::TearDown() {
void Heap::AddGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
GCType gc_type, void* data) {
DCHECK_NOT_NULL(callback);
- DCHECK(gc_prologue_callbacks_.end() ==
- std::find(gc_prologue_callbacks_.begin(), gc_prologue_callbacks_.end(),
- GCCallbackTuple(callback, gc_type, data)));
+// DCHECK(gc_prologue_callbacks_.end() ==
+// std::find(gc_prologue_callbacks_.begin(), gc_prologue_callbacks_.end(),
+// GCCallbackTuple(callback, gc_type, data)));
gc_prologue_callbacks_.emplace_back(callback, gc_type, data);
}

View file

@ -0,0 +1,15 @@
diff --git a/test/unittests/base/bits-unittest.cc b/test/unittests/base/bits-unittest.cc
index 45fb921797..8c9f249609 100644
--- a/test/unittests/base/bits-unittest.cc
+++ b/test/unittests/base/bits-unittest.cc
@@ -13,7 +13,9 @@
#else
#define DISABLE_IN_RELEASE(Name) DISABLED_##Name
#endif
-
+#ifdef _WIN32
+#pragma warning(disable:4724 4723) // Disable potential divide by 0 warnings
+#endif
namespace v8 {
namespace base {
namespace bits {

View file

@ -0,0 +1,21 @@
diff --git a/include/v8-platform.h b/include/v8-platform.h
index ddc200abab..046de4e257 100644
--- a/include/v8-platform.h
+++ b/include/v8-platform.h
@@ -11,6 +11,7 @@
#include <memory>
#include <string>
+#include "v8.h"
#include "v8config.h" // NOLINT(build/include)
namespace v8 {
@@ -465,7 +466,7 @@ class Platform {
* since epoch. Useful for implementing |CurrentClockTimeMillis| if
* nothing special needed.
*/
- static double SystemClockTimeMillis();
+ V8_EXPORT static double SystemClockTimeMillis();
};
} // namespace v8

View file

@ -0,0 +1,13 @@
diff --git a/src/ostreams.h b/src/ostreams.h
index e72c8ee..9f25bca 100644
--- a/src/ostreams.h
+++ b/src/ostreams.h
@@ -34,7 +34,7 @@ class OFStreamBase : public std::streambuf {
// An output stream writing to a file.
-class V8_EXPORT_PRIVATE OFStream : public std::ostream {
+class V8_EXPORT_PRIVATE OFStream : public NON_EXPORTED_BASE(std::ostream) {
public:
explicit OFStream(FILE* f);
virtual ~OFStream();