| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent d8011d1 commit 7fb128d
9 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5370,6 +5370,19 @@ class V8_EXPORT Isolate { | |||
| 5370 | 5370 | */ | |
| 5371 | 5371 | static Isolate* GetCurrent(); | |
| 5372 | 5372 | ||
| 5373 | + /** | ||
| 5374 | + * Custom callback used by embedders to help V8 determine if it should abort | ||
| 5375 | + * when it throws and no internal handler is predicted to catch the | ||
| 5376 | + * exception. If --abort-on-uncaught-exception is used on the command line, | ||
| 5377 | + * then V8 will abort if either: | ||
| 5378 | + * - no custom callback is set. | ||
| 5379 | + * - the custom callback set returns true. | ||
| 5380 | + * Otherwise, the custom callback will not be called and V8 will not abort. | ||
| 5381 | + */ | ||
| 5382 | + typedef bool (*AbortOnUncaughtExceptionCallback)(Isolate*); | ||
| 5383 | + void SetAbortOnUncaughtExceptionCallback( | ||
| 5384 | + AbortOnUncaughtExceptionCallback callback); | ||
| 5385 | + | ||
| 5373 | 5386 | /** | |
| 5374 | 5387 | * Methods below this point require holding a lock (using Locker) in | |
| 5375 | 5388 | * a multi-threaded environment. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -99,22 +99,37 @@ bool Accessors::IsJSArrayBufferViewFieldAccessor(Handle<Map> map, | |||
| 99 | 99 | Isolate* isolate = name->GetIsolate(); | |
| 100 | 100 | ||
| 101 | 101 | switch (map->instance_type()) { | |
| 102 | - case JS_TYPED_ARRAY_TYPE: | ||
| 103 | - // %TypedArray%.prototype is non-configurable, and so are the following | ||
| 104 | - // named properties on %TypedArray%.prototype, so we can directly inline | ||
| 105 | - // the field-load for typed array maps that still use their | ||
| 106 | - // %TypedArray%.prototype. | ||
| 107 | - if (JSFunction::cast(map->GetConstructor())->prototype() != | ||
| 108 | - map->prototype()) { | ||
| 102 | + case JS_TYPED_ARRAY_TYPE: { | ||
| 103 | + if (!CheckForName(name, isolate->factory()->length_string(), | ||
| 104 | + JSTypedArray::kLengthOffset, object_offset) && | ||
| 105 | + !CheckForName(name, isolate->factory()->byte_length_string(), | ||
| 106 | + JSTypedArray::kByteLengthOffset, object_offset) && | ||
| 107 | + !CheckForName(name, isolate->factory()->byte_offset_string(), | ||
| 108 | + JSTypedArray::kByteOffsetOffset, object_offset)) { | ||
| 109 | 109 | return false; | |
| 110 | 110 | } | |
| 111 | - return CheckForName(name, isolate->factory()->length_string(), | ||
| 112 | - JSTypedArray::kLengthOffset, object_offset) || | ||
| 113 | - CheckForName(name, isolate->factory()->byte_length_string(), | ||
| 114 | - JSTypedArray::kByteLengthOffset, object_offset) || | ||
| 115 | - CheckForName(name, isolate->factory()->byte_offset_string(), | ||
| 116 | - JSTypedArray::kByteOffsetOffset, object_offset); | ||
| 117 | 111 | ||
| 112 | + if (map->is_dictionary_map()) return false; | ||
| 113 | + | ||
| 114 | + // Check if the property is overridden on the instance. | ||
| 115 | + DescriptorArray* descriptors = map->instance_descriptors(); | ||
| 116 | + int descriptor = descriptors->SearchWithCache(*name, *map); | ||
| 117 | + if (descriptor != DescriptorArray::kNotFound) return false; | ||
| 118 | + | ||
| 119 | + Handle<Object> proto = Handle<Object>(map->prototype(), isolate); | ||
| 120 | + if (!proto->IsJSReceiver()) return false; | ||
| 121 | + | ||
| 122 | + // Check if the property is defined in the prototype chain. | ||
| 123 | + LookupIterator it(proto, name); | ||
| 124 | + if (!it.IsFound()) return false; | ||
| 125 | + | ||
| 126 | + Object* original_proto = | ||
| 127 | + JSFunction::cast(map->GetConstructor())->prototype(); | ||
| 128 | + | ||
| 129 | + // Property is not configurable. It is enough to verify that | ||
| 130 | + // the holder is the same. | ||
| 131 | + return *it.GetHolder<Object>() == original_proto; | ||
| 132 | + } | ||
| 118 | 133 | case JS_DATA_VIEW_TYPE: | |
| 119 | 134 | return CheckForName(name, isolate->factory()->byte_length_string(), | |
| 120 | 135 | JSDataView::kByteLengthOffset, object_offset) || | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7160,6 +7160,13 @@ void Isolate::Exit() { | |||
| 7160 | 7160 | } | |
| 7161 | 7161 | ||
| 7162 | 7162 | ||
| 7163 | + void Isolate::SetAbortOnUncaughtExceptionCallback( | ||
| 7164 | + AbortOnUncaughtExceptionCallback callback) { | ||
| 7165 | + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); | ||
| 7166 | + isolate->SetAbortOnUncaughtExceptionCallback(callback); | ||
| 7167 | + } | ||
| 7168 | + | ||
| 7169 | + | ||
| 7163 | 7170 | Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope( | |
| 7164 | 7171 | Isolate* isolate, | |
| 7165 | 7172 | Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1013,13 +1013,21 @@ Object* Isolate::Throw(Object* exception, MessageLocation* location) { | |||
| 1013 | 1013 | Handle<Object> message_obj = CreateMessage(exception_handle, location); | |
| 1014 | 1014 | thread_local_top()->pending_message_obj_ = *message_obj; | |
| 1015 | 1015 | ||
| 1016 | - // If the abort-on-uncaught-exception flag is specified, abort on any | ||
| 1017 | - // exception not caught by JavaScript, even when an external handler is | ||
| 1018 | - // present. This flag is intended for use by JavaScript developers, so | ||
| 1019 | - // print a user-friendly stack trace (not an internal one). | ||
| 1016 | + // For any exception not caught by JavaScript, even when an external | ||
| 1017 | + // handler is present: | ||
| 1018 | + // If the abort-on-uncaught-exception flag is specified, and if the | ||
| 1019 | + // embedder didn't specify a custom uncaught exception callback, | ||
| 1020 | + // or if the custom callback determined that V8 should abort, then | ||
| 1021 | + // abort. | ||
| 1020 | 1022 | if (FLAG_abort_on_uncaught_exception && | |
| 1021 | - PredictExceptionCatcher() != CAUGHT_BY_JAVASCRIPT) { | ||
| 1022 | - FLAG_abort_on_uncaught_exception = false; // Prevent endless recursion. | ||
| 1023 | + PredictExceptionCatcher() != CAUGHT_BY_JAVASCRIPT && | ||
| 1024 | + (!abort_on_uncaught_exception_callback_ || | ||
| 1025 | + abort_on_uncaught_exception_callback_( | ||
| 1026 | + reinterpret_cast<v8::Isolate*>(this)))) { | ||
| 1027 | + // Prevent endless recursion. | ||
| 1028 | + FLAG_abort_on_uncaught_exception = false; | ||
| 1029 | + // This flag is intended for use by JavaScript developers, so | ||
| 1030 | + // print a user-friendly stack trace (not an internal one). | ||
| 1023 | 1031 | PrintF(stderr, "%s\n\nFROM\n", | |
| 1024 | 1032 | MessageHandler::GetLocalizedMessage(this, message_obj).get()); | |
| 1025 | 1033 | PrintCurrentStackTrace(stderr); | |
@@ -1607,6 +1615,12 @@ void Isolate::SetCaptureStackTraceForUncaughtExceptions( | |||
| 1607 | 1615 | } | |
| 1608 | 1616 | ||
| 1609 | 1617 | ||
| 1618 | + void Isolate::SetAbortOnUncaughtExceptionCallback( | ||
| 1619 | + v8::Isolate::AbortOnUncaughtExceptionCallback callback) { | ||
| 1620 | + abort_on_uncaught_exception_callback_ = callback; | ||
| 1621 | + } | ||
| 1622 | + | ||
| 1623 | + | ||
| 1610 | 1624 | Handle<Context> Isolate::native_context() { | |
| 1611 | 1625 | return handle(context()->native_context()); | |
| 1612 | 1626 | } | |
@@ -1774,7 +1788,8 @@ Isolate::Isolate(bool enable_serializer) | |||
| 1774 | 1788 | next_unique_sfi_id_(0), | |
| 1775 | 1789 | #endif | |
| 1776 | 1790 | use_counter_callback_(NULL), | |
| 1777 | - basic_block_profiler_(NULL) { | ||
| 1791 | + basic_block_profiler_(NULL), | ||
| 1792 | + abort_on_uncaught_exception_callback_(NULL) { | ||
| 1778 | 1793 | { | |
| 1779 | 1794 | base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); | |
| 1780 | 1795 | CHECK(thread_data_table_); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -698,6 +698,9 @@ class Isolate { | |||
| 698 | 698 | int frame_limit, | |
| 699 | 699 | StackTrace::StackTraceOptions options); | |
| 700 | 700 | ||
| 701 | + void SetAbortOnUncaughtExceptionCallback( | ||
| 702 | + v8::Isolate::AbortOnUncaughtExceptionCallback callback); | ||
| 703 | + | ||
| 701 | 704 | enum PrintStackMode { kPrintStackConcise, kPrintStackVerbose }; | |
| 702 | 705 | void PrintCurrentStackTrace(FILE* out); | |
| 703 | 706 | void PrintStack(StringStream* accumulator, | |
@@ -1366,6 +1369,9 @@ class Isolate { | |||
| 1366 | 1369 | ||
| 1367 | 1370 | std::set<Cancelable*> cancelable_tasks_; | |
| 1368 | 1371 | ||
| 1372 | + v8::Isolate::AbortOnUncaughtExceptionCallback | ||
| 1373 | + abort_on_uncaught_exception_callback_; | ||
| 1374 | + | ||
| 1369 | 1375 | friend class ExecutionAccess; | |
| 1370 | 1376 | friend class HandleScopeImplementer; | |
| 1371 | 1377 | friend class OptimizingCompileDispatcher; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3932,14 +3932,14 @@ class ScopeInfo : public FixedArray { | |||
| 3932 | 3932 | FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS) | |
| 3933 | 3933 | #undef FIELD_ACCESSORS | |
| 3934 | 3934 | ||
| 3935 | - private: | ||
| 3936 | 3935 | enum { | |
| 3937 | 3936 | #define DECL_INDEX(name) k##name, | |
| 3938 | 3937 | FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX) | |
| 3939 | 3938 | #undef DECL_INDEX | |
| 3940 | 3939 | kVariablePartIndex | |
| 3941 | 3940 | }; | |
| 3942 | 3941 | ||
| 3942 | + private: | ||
| 3943 | 3943 | // The layout of the variable part of a ScopeInfo is as follows: | |
| 3944 | 3944 | // 1. ParameterEntries: | |
| 3945 | 3945 | // This part stores the names of the parameters for function scopes. One | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -21826,4 +21826,34 @@ TEST(EstimatedContextSize) { | |||
| 21826 | 21826 | v8::HandleScope scope(isolate); | |
| 21827 | 21827 | LocalContext env; | |
| 21828 | 21828 | CHECK(50000 < env->EstimatedSize()); | |
| 21829 | + | ||
| 21830 | + | ||
| 21831 | + static int nb_uncaught_exception_callback_calls = 0; | ||
| 21832 | + | ||
| 21833 | + | ||
| 21834 | + bool NoAbortOnUncaughtException(v8::Isolate* isolate) { | ||
| 21835 | + ++nb_uncaught_exception_callback_calls; | ||
| 21836 | + return false; | ||
| 21837 | + } | ||
| 21838 | + | ||
| 21839 | + | ||
| 21840 | + TEST(AbortOnUncaughtExceptionNoAbort) { | ||
| 21841 | + v8::Isolate* isolate = CcTest::isolate(); | ||
| 21842 | + v8::HandleScope handle_scope(isolate); | ||
| 21843 | + v8::Handle<v8::ObjectTemplate> global_template = | ||
| 21844 | + v8::ObjectTemplate::New(isolate); | ||
| 21845 | + LocalContext env(NULL, global_template); | ||
| 21846 | + | ||
| 21847 | + i::FLAG_abort_on_uncaught_exception = true; | ||
| 21848 | + isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException); | ||
| 21849 | + | ||
| 21850 | + CompileRun("function boom() { throw new Error(\"boom\") }"); | ||
| 21851 | + | ||
| 21852 | + v8::Local<v8::Object> global_object = env->Global(); | ||
| 21853 | + v8::Local<v8::Function> foo = | ||
| 21854 | + v8::Local<v8::Function>::Cast(global_object->Get(v8_str("boom"))); | ||
| 21855 | + | ||
| 21856 | + foo->Call(global_object, 0, NULL); | ||
| 21857 | + | ||
| 21858 | + CHECK_EQ(1, nb_uncaught_exception_callback_calls); | ||
| 21829 | 21859 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -71,6 +71,43 @@ assertEquals(undefined, get(a)); | |||
| 71 | 71 | assertEquals(undefined, get(a)); | |
| 72 | 72 | })(); | |
| 73 | 73 | ||
| 74 | + (function() { | ||
| 75 | + "use strict"; | ||
| 76 | + | ||
| 77 | + class MyTypedArray extends Int32Array { | ||
| 78 | + constructor(length) { | ||
| 79 | + super(length); | ||
| 80 | + } | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + a = new MyTypedArray(1024); | ||
| 84 | + | ||
| 85 | + get = function(a) { | ||
| 86 | + return a.length; | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + assertEquals(1024, get(a)); | ||
| 90 | + assertEquals(1024, get(a)); | ||
| 91 | + assertEquals(1024, get(a)); | ||
| 92 | + %OptimizeFunctionOnNextCall(get); | ||
| 93 | + assertEquals(1024, get(a)); | ||
| 94 | + })(); | ||
| 95 | + | ||
| 96 | + (function() { | ||
| 97 | + "use strict"; | ||
| 98 | + var a = new Uint8Array(4); | ||
| 99 | + Object.defineProperty(a, "length", {get: function() { return "blah"; }}); | ||
| 100 | + get = function(a) { | ||
| 101 | + return a.length; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + assertEquals("blah", get(a)); | ||
| 105 | + assertEquals("blah", get(a)); | ||
| 106 | + assertEquals("blah", get(a)); | ||
| 107 | + %OptimizeFunctionOnNextCall(get); | ||
| 108 | + assertEquals("blah", get(a)); | ||
| 109 | + })(); | ||
| 110 | + | ||
| 74 | 111 | // Ensure we cannot delete length, byteOffset, byteLength. | |
| 75 | 112 | assertTrue(Int32Array.prototype.hasOwnProperty("length")); | |
| 76 | 113 | assertTrue(Int32Array.prototype.hasOwnProperty("byteOffset")); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -132,6 +132,15 @@ | |||
| 132 | 132 | 'value': 'JavaScriptFrameConstants::kFunctionOffset' }, | |
| 133 | 133 | { 'name': 'off_fp_args', | |
| 134 | 134 | 'value': 'JavaScriptFrameConstants::kLastParameterOffset' }, | |
| 135 | + | ||
| 136 | + { 'name': 'scopeinfo_idx_nparams', | ||
| 137 | + 'value': 'ScopeInfo::kParameterCount' }, | ||
| 138 | + { 'name': 'scopeinfo_idx_nstacklocals', | ||
| 139 | + 'value': 'ScopeInfo::kStackLocalCount' }, | ||
| 140 | + { 'name': 'scopeinfo_idx_ncontextlocals', | ||
| 141 | + 'value': 'ScopeInfo::kContextLocalCount' }, | ||
| 142 | + { 'name': 'scopeinfo_idx_first_vars', | ||
| 143 | + 'value': 'ScopeInfo::kVariablePartIndex' }, | ||
| 135 | 144 | ]; | |
| 136 | 145 | ||
| 137 | 146 | # | |
@@ -141,12 +150,13 @@ | |||
| 141 | 150 | 'HeapObject, map, Map, kMapOffset', | |
| 142 | 151 | 'JSObject, elements, Object, kElementsOffset', | |
| 143 | 152 | 'FixedArray, data, uintptr_t, kHeaderSize', | |
| 153 | + 'JSTypedArray, length, Object, kLengthOffset', | ||
| 144 | 154 | 'Map, instance_attributes, int, kInstanceAttributesOffset', | |
| 145 | 155 | 'Map, inobject_properties_of_constructor_function_index_offset, int, kInObjectPropertiesOrConstructorFunctionIndexOffset', | |
| 146 | 156 | 'Map, instance_size, int, kInstanceSizeOffset', | |
| 147 | 157 | 'Map, bit_field, char, kBitFieldOffset', | |
| 148 | 158 | 'Map, bit_field2, char, kBitField2Offset', | |
| 149 | - 'Map, bit_field3, SMI, kBitField3Offset', | ||
| 159 | + 'Map, bit_field3, int, kBitField3Offset', | ||
| 150 | 160 | 'Map, prototype, Object, kPrototypeOffset', | |
| 151 | 161 | 'NameDictionaryShape, prefix_size, int, kPrefixSize', | |
| 152 | 162 | 'NameDictionaryShape, entry_size, int, kEntrySize', | |
| Back | FazBrowse Home | New Git URL |
0 commit comments