From fca51c7db724704100df9cc36bb89807f4e7b9b7 Mon Sep 17 00:00:00 2001 From: denvash Date: Mon, 18 Feb 2019 15:34:08 +0200 Subject: [PATCH] [+] demos --- .gitignore | 54 + .markdownlint.json | 11 + .npmignore | 75 + .release-it.json | 30 + demo/.editorconfig | 14 + demo/.vscode/settings.json | 3 + demo/Cryptarithm.js | 60 + demo/checkbox_with_label.test.js | 22 + demo/clojure.clj | 26 + demo/clojurescript.cljs | 21 + demo/cplusplus-header.h | 616 ++ demo/cplusplus-source.cc | 10714 +++++++++++++++++++++++++++++ demo/css.css | 11 + demo/elm.elm | 8 + demo/html.html | 24 + demo/issue-91.jsx | 29 + demo/issue-91.tsx | 29 + demo/js.js | 58 + demo/json.json | 14 + demo/markdown.md | 15 + demo/php.php | 36 + demo/powershell.ps1 | 68 + demo/pug.pug | 11 + demo/python.py | 22 + demo/react.js | 31 + demo/ruby.rb | 47 + demo/statelessfunctionalreact.js | 31 + demo/tsx.tsx | 44 + demo/typescript.ts | 63 + demo/vuedemo.vue | 42 + demo/yml.yml | 13 + images/color-palette-titled.png | Bin 0 -> 26482 bytes images/color-palette.png | Bin 0 -> 3845 bytes images/example-js.png | Bin 0 -> 258835 bytes images/example-react.png | Bin 0 -> 213503 bytes images/logo-github.png | Bin 0 -> 83357 bytes images/logo-titled.png | Bin 0 -> 24153 bytes images/logo.png | Bin 0 -> 12113 bytes package-lock.json | 5680 +++++++++++++++ package.json | 52 +- 40 files changed, 17968 insertions(+), 6 deletions(-) create mode 100644 .gitignore create mode 100644 .markdownlint.json create mode 100644 .npmignore create mode 100644 .release-it.json create mode 100644 demo/.editorconfig create mode 100644 demo/.vscode/settings.json create mode 100644 demo/Cryptarithm.js create mode 100644 demo/checkbox_with_label.test.js create mode 100644 demo/clojure.clj create mode 100644 demo/clojurescript.cljs create mode 100644 demo/cplusplus-header.h create mode 100644 demo/cplusplus-source.cc create mode 100644 demo/css.css create mode 100644 demo/elm.elm create mode 100644 demo/html.html create mode 100644 demo/issue-91.jsx create mode 100644 demo/issue-91.tsx create mode 100644 demo/js.js create mode 100644 demo/json.json create mode 100644 demo/markdown.md create mode 100644 demo/php.php create mode 100644 demo/powershell.ps1 create mode 100644 demo/pug.pug create mode 100644 demo/python.py create mode 100644 demo/react.js create mode 100644 demo/ruby.rb create mode 100644 demo/statelessfunctionalreact.js create mode 100644 demo/tsx.tsx create mode 100644 demo/typescript.ts create mode 100644 demo/vuedemo.vue create mode 100644 demo/yml.yml create mode 100644 images/color-palette-titled.png create mode 100644 images/color-palette.png create mode 100644 images/example-js.png create mode 100644 images/example-react.png create mode 100644 images/logo-github.png create mode 100644 images/logo-titled.png create mode 100644 images/logo.png create mode 100644 package-lock.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f81505 --- /dev/null +++ b/.gitignore @@ -0,0 +1,54 @@ +# NPM # +########## +# Ignore all directories called node_modules in current folder and any subfolders. +node_modules/ +/node_modules/ + +# Packages # +############ +*.7z +*.dmg +*.gz +*.bz2 +*.iso +*.jar +*.rar +*.tar +*.zip +*.tgz +*.map + +# Logs and databases # +###################### +*.log +*.sql +*.env + +# OS generated files # +###################### +**.DS_Store* +ehthumbs.db +Icon? +Thumbs.db +._* + +# Vim generated files # +###################### +*.un~ + +# SASS # +########## +**/.sass-cache +**/.sass-cache/* +**/.map + +# Composer # +########## +!assets/js/vendor/ +wpcs/ +/vendor/ + + +# Project related +################# +images/inspire.png diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..88a556f --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,11 @@ +{ + "default": true, + "MD041": false, + "MD010": false, + "MD002": false, + "MD001": false, + "MD022": false, + "MD024": false, + "MD013": false, + "MD033": false +} diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..7037aeb --- /dev/null +++ b/.npmignore @@ -0,0 +1,75 @@ +# NPM # +########## +# Ignore all directories called node_modules in current folder and any subfolders. +node_modules/ +/node_modules/ + +# Packages # +############ +*.7z +*.dmg +*.gz +*.bz2 +*.iso +*.jar +*.rar +*.tar +*.zip +*.tgz +*.map + +# Logs and databases # +###################### +*.log +*.sql +*.env + +# OS generated files # +###################### +**.DS_Store* +ehthumbs.db +Icon? +Thumbs.db +._* + +# Vim generated files # +###################### +*.un~ + +# SASS # +########## +**/.sass-cache +**/.sass-cache/* +**/.map + +# Composer # +########## +!assets/js/vendor/ +wpcs/ +/vendor/ + +# Bower # +########## +assets/bower_components/* + +# Codekit # +########## +/codekit-config.json +*.codekit +**.codekit-cache/* + +# Compiled Files and Build Dirs # +########## +/README.html + +# PhpStrom Project Files # +.idea/ +library/vendors/composer +assets/img/.DS_Store + +# NPM Ignore. +/imgages +/demo +/.vscode +images/shades-of-purple.gif +images/shades-of-purple.jpg diff --git a/.release-it.json b/.release-it.json new file mode 100644 index 0000000..493467d --- /dev/null +++ b/.release-it.json @@ -0,0 +1,30 @@ +{ + "dry-run": false, + "verbose": false, + "force": true, + "non-interactive": true, + "increment": "minor", + "beforeChangelogCommand": "auto-changelog", + "safeBump": false, + "src": { + "commitMessage": "🍧 Release %s", + "tagAnnotation": "🍧 Release %s" + }, + "npm": { + "publish": true + }, + "github": { + "release": true, + "releaseName": "🍧 %s" + }, + "prompt": { + "src": { + "status": true, + "commit": true, + "tag": true, + "push": true, + "release": true, + "publish": true + } + } +} diff --git a/demo/.editorconfig b/demo/.editorconfig new file mode 100644 index 0000000..a119f4d --- /dev/null +++ b/demo/.editorconfig @@ -0,0 +1,14 @@ +# http://editorconfig.org +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/demo/.vscode/settings.json b/demo/.vscode/settings.json new file mode 100644 index 0000000..625247d --- /dev/null +++ b/demo/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.linting.enabled": false +} \ No newline at end of file diff --git a/demo/Cryptarithm.js b/demo/Cryptarithm.js new file mode 100644 index 0000000..70fbc6b --- /dev/null +++ b/demo/Cryptarithm.js @@ -0,0 +1,60 @@ +// https://www.codingame.com/training/hard/cryptarithm + +/** + * Generates all permutations of a set. + * @param {Array|String} arr - The set of elements. + * @param {Number} size - Number of elements to choose from the set. + */ +function* permutation(arr, size = arr.length) { + const data = []; + const indicesUsed = []; + yield* permutationUtil(0); + + /** + * @param {Number} index of permutation + * @return {Generator} + */ + function* permutationUtil(index) { + if (index === size) { + return yield this.clones ? data.slice() : data; + } + for (let i = 0; i < arr.length; i++) { + if (!indicesUsed[i]) { + indicesUsed[i] = true; + data[index] = arr[i]; + yield* permutationUtil(index + 1); + indicesUsed[i] = false; + } + } + } +} + +// We generate a permutation and checking if the sum is valid +const r = () => readline().split(''); +const words = [...Array(+readline())].map(() => r()); +const wordsTotal = r(); + +const dictionary = [...new Set([...words, wordsTotal].flat())].sort(); + +const permutationGenerator = + permutation([...Array(10).keys()], dictionary.length); + +for (let permutation of permutationGenerator) { + const keyValueArray = dictionary.map((v, i) => [v, permutation[i]]); + const cryptMap = new Map(keyValueArray); + if (cryptMap.get(wordsTotal[0]) === 0) continue; + + const wordToNumber = + (arr) => +arr.map((char) => cryptMap.get(char)).join(''); + + const sumWords = + words.map((word) => wordToNumber(word)) + .reduce((sum, curr) => sum+=curr); + + const sumTotal = wordToNumber(wordsTotal); + + if (sumWords === sumTotal) { + cryptMap.forEach((value, key) => console.log(key, value)); + break; + } +} diff --git a/demo/checkbox_with_label.test.js b/demo/checkbox_with_label.test.js new file mode 100644 index 0000000..2e3b990 --- /dev/null +++ b/demo/checkbox_with_label.test.js @@ -0,0 +1,22 @@ +import React from 'react' +import ReactDOM from 'react-dom' +import * as TestUtils from 'react-dom/test-utils' +import CheckboxWithLabel from '../CheckboxWithLabel' + +it('CheckboxWithLabel changes the text after click', () => { + // Render a checkbox with label in the document + const checkbox = TestUtils.renderIntoDocument( + + ) + + const checkboxNode = ReactDOM.findDOMNode(checkbox) + + // Verify that it's Off by default + expect(checkboxNode.textContent).toEqual('Off') + + // Simulate a click and verify that it is now On + TestUtils.Simulate.change( + TestUtils.findRenderedDOMComponentWithTag(checkbox, 'input') + ) + expect(checkboxNode.textContent).toEqual('On') +}) diff --git a/demo/clojure.clj b/demo/clojure.clj new file mode 100644 index 0000000..d4da277 --- /dev/null +++ b/demo/clojure.clj @@ -0,0 +1,26 @@ +(ns hello.world.clojure) + +(defn sum [& numbers] + (if (empty? numbers) + 0 + (reduce + 0 numbers))) + +(defn print-name [{:keys [first last age]}] + (println (str "Your name is " first " " last " and you are " age " years old."))) + +(defn set-age [person new-age] + (assoc person :age new-age)) + +(defn hello-world [] + (let [john {:first "John" :last "Smith" :age 65} + jack {:first "Jack" :last "Road" :age 76} + george {:first "George" :last "Way" :age 23} + george-junior (assoc george :age 6) + all-persons [john jack george george-junior]] + + (doseq [person all-persons] + (print-name person)) + + (println (str "Total age is: " (apply sum (map :age all-persons)))))) + +(hello-world) diff --git a/demo/clojurescript.cljs b/demo/clojurescript.cljs new file mode 100644 index 0000000..9aed834 --- /dev/null +++ b/demo/clojurescript.cljs @@ -0,0 +1,21 @@ +(ns hello.world.clojurescript + (:require [reagent.core :as r]) + +(def counter (r/atom 0)) +(def text-component-style {:background-color :grey + :border "1px solid black" + :padding "5px"}) + +(defn counter-clicked [] + (.log js/console "You clicked the counter component.") + (swap! counter inc)) + +(defn text-counter [text] + [:div {:on-click counter-clicked + :style text-component-style}) + (str text @counter]) + +(defn main-component [] + [:div + [:p {:style {:color :red}} "Hello world! Click the element below:"] + [text-counter "Clicked: "]]) diff --git a/demo/cplusplus-header.h b/demo/cplusplus-header.h new file mode 100644 index 0000000..e5f5c7d --- /dev/null +++ b/demo/cplusplus-header.h @@ -0,0 +1,616 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_API_H_ +#define V8_API_H_ + +#include "include/v8-testing.h" +#include "src/contexts.h" +#include "src/debug/debug-interface.h" +#include "src/detachable-vector.h" +#include "src/heap/factory.h" +#include "src/isolate.h" +#include "src/objects.h" +#include "src/objects/bigint.h" +#include "src/objects/js-collection.h" +#include "src/objects/js-generator.h" +#include "src/objects/js-promise.h" +#include "src/objects/js-proxy.h" +#include "src/objects/module.h" +#include "src/objects/shared-function-info.h" + +#include "src/objects/templates.h" + +namespace v8 { + +// Constants used in the implementation of the API. The most natural thing +// would usually be to place these with the classes that use them, but +// we want to keep them out of v8.h because it is an externally +// visible file. +class Consts { + public: + enum TemplateType { + FUNCTION_TEMPLATE = 0, + OBJECT_TEMPLATE = 1 + }; +}; + +template +inline T ToCData(v8::internal::Object* obj); + +template <> +inline v8::internal::Address ToCData(v8::internal::Object* obj); + +template +inline v8::internal::Handle FromCData( + v8::internal::Isolate* isolate, T obj); + +template <> +inline v8::internal::Handle FromCData( + v8::internal::Isolate* isolate, v8::internal::Address obj); + +class ApiFunction { + public: + explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { } + v8::internal::Address address() { return addr_; } + private: + v8::internal::Address addr_; +}; + + + +class RegisteredExtension { + public: + explicit RegisteredExtension(Extension* extension); + static void Register(RegisteredExtension* that); + static void UnregisterAll(); + Extension* extension() { return extension_; } + RegisteredExtension* next() { return next_; } + static RegisteredExtension* first_extension() { return first_extension_; } + private: + Extension* extension_; + RegisteredExtension* next_; + static RegisteredExtension* first_extension_; +}; + +#define OPEN_HANDLE_LIST(V) \ + V(Template, TemplateInfo) \ + V(FunctionTemplate, FunctionTemplateInfo) \ + V(ObjectTemplate, ObjectTemplateInfo) \ + V(Signature, FunctionTemplateInfo) \ + V(AccessorSignature, FunctionTemplateInfo) \ + V(Data, Object) \ + V(RegExp, JSRegExp) \ + V(Object, JSReceiver) \ + V(Array, JSArray) \ + V(Map, JSMap) \ + V(Set, JSSet) \ + V(ArrayBuffer, JSArrayBuffer) \ + V(ArrayBufferView, JSArrayBufferView) \ + V(TypedArray, JSTypedArray) \ + V(Uint8Array, JSTypedArray) \ + V(Uint8ClampedArray, JSTypedArray) \ + V(Int8Array, JSTypedArray) \ + V(Uint16Array, JSTypedArray) \ + V(Int16Array, JSTypedArray) \ + V(Uint32Array, JSTypedArray) \ + V(Int32Array, JSTypedArray) \ + V(Float32Array, JSTypedArray) \ + V(Float64Array, JSTypedArray) \ + V(DataView, JSDataView) \ + V(SharedArrayBuffer, JSArrayBuffer) \ + V(Name, Name) \ + V(String, String) \ + V(Symbol, Symbol) \ + V(Script, JSFunction) \ + V(UnboundModuleScript, SharedFunctionInfo) \ + V(UnboundScript, SharedFunctionInfo) \ + V(Module, Module) \ + V(Function, JSReceiver) \ + V(Message, JSMessageObject) \ + V(Context, Context) \ + V(External, Object) \ + V(StackTrace, FixedArray) \ + V(StackFrame, StackFrameInfo) \ + V(Proxy, JSProxy) \ + V(debug::GeneratorObject, JSGeneratorObject) \ + V(debug::Script, Script) \ + V(debug::WeakMap, JSWeakMap) \ + V(Promise, JSPromise) \ + V(Primitive, Object) \ + V(PrimitiveArray, FixedArray) \ + V(BigInt, BigInt) \ + V(ScriptOrModule, Script) + +class Utils { + public: + static inline bool ApiCheck(bool condition, + const char* location, + const char* message) { + if (!condition) Utils::ReportApiFailure(location, message); + return condition; + } + static void ReportOOMFailure(v8::internal::Isolate* isolate, + const char* location, bool is_heap_oom); + + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocalUint8Array( + v8::internal::Handle obj); + static inline Local ToLocalUint8ClampedArray( + v8::internal::Handle obj); + static inline Local ToLocalInt8Array( + v8::internal::Handle obj); + static inline Local ToLocalUint16Array( + v8::internal::Handle obj); + static inline Local ToLocalInt16Array( + v8::internal::Handle obj); + static inline Local ToLocalUint32Array( + v8::internal::Handle obj); + static inline Local ToLocalInt32Array( + v8::internal::Handle obj); + static inline Local ToLocalFloat32Array( + v8::internal::Handle obj); + static inline Local ToLocalFloat64Array( + v8::internal::Handle obj); + static inline Local ToLocalBigInt64Array( + v8::internal::Handle obj); + static inline Local ToLocalBigUint64Array( + v8::internal::Handle obj); + + static inline Local ToLocalShared( + v8::internal::Handle obj); + + static inline Local MessageToLocal( + v8::internal::Handle obj); + static inline Local PromiseToLocal( + v8::internal::Handle obj); + static inline Local StackTraceToLocal( + v8::internal::Handle obj); + static inline Local StackFrameToLocal( + v8::internal::Handle obj); + static inline Local NumberToLocal( + v8::internal::Handle obj); + static inline Local IntegerToLocal( + v8::internal::Handle obj); + static inline Local Uint32ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local SignatureToLocal( + v8::internal::Handle obj); + static inline Local AccessorSignatureToLocal( + v8::internal::Handle obj); + static inline Local ExternalToLocal( + v8::internal::Handle obj); + static inline Local CallableToLocal( + v8::internal::Handle obj); + static inline Local ToLocalPrimitive( + v8::internal::Handle obj); + static inline Local ToLocal( + v8::internal::Handle obj); + static inline Local ScriptOrModuleToLocal( + v8::internal::Handle obj); + +#define DECLARE_OPEN_HANDLE(From, To) \ + static inline v8::internal::Handle \ + OpenHandle(const From* that, bool allow_empty_handle = false); + +OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE) + +#undef DECLARE_OPEN_HANDLE + +template +static inline Local Convert(v8::internal::Handle obj); + +template +static inline v8::internal::Handle OpenPersistent( + const v8::Persistent& persistent) { + return v8::internal::Handle( + reinterpret_cast(persistent.val_)); + } + + template + static inline v8::internal::Handle OpenPersistent( + v8::Persistent* persistent) { + return OpenPersistent(*persistent); + } + + template + static inline v8::internal::Handle OpenHandle(v8::Local handle) { + return OpenHandle(*handle); + } + + private: + static void ReportApiFailure(const char* location, const char* message); +}; + + +template +inline T* ToApi(v8::internal::Handle obj) { + return reinterpret_cast(obj.location()); +} + +template +inline v8::Local ToApiHandle( + v8::internal::Handle obj) { + return Utils::Convert(obj); +} + + +template +inline bool ToLocal(v8::internal::MaybeHandle maybe, + Local* local) { + v8::internal::Handle handle; + if (maybe.ToHandle(&handle)) { + *local = Utils::Convert(handle); + return true; + } + return false; +} + +namespace internal { + +class V8_EXPORT_PRIVATE DeferredHandles { + public: + ~DeferredHandles(); + + private: + DeferredHandles(Object** first_block_limit, Isolate* isolate) + : next_(nullptr), + previous_(nullptr), + first_block_limit_(first_block_limit), + isolate_(isolate) { + isolate->LinkDeferredHandles(this); + } + + void Iterate(RootVisitor* v); + + std::vector blocks_; + DeferredHandles* next_; + DeferredHandles* previous_; + Object** first_block_limit_; + Isolate* isolate_; + + friend class HandleScopeImplementer; + friend class Isolate; +}; + + +// This class is here in order to be able to declare it a friend of +// HandleScope. Moving these methods to be members of HandleScope would be +// neat in some ways, but it would expose internal implementation details in +// our public header file, which is undesirable. +// +// An isolate has a single instance of this class to hold the current thread's +// data. In multithreaded V8 programs this data is copied in and out of storage +// so that the currently executing thread always has its own copy of this +// data. +class HandleScopeImplementer { + public: + explicit HandleScopeImplementer(Isolate* isolate) + : isolate_(isolate), + microtask_context_(nullptr), + spare_(nullptr), + call_depth_(0), + microtasks_depth_(0), + microtasks_suppressions_(0), + entered_contexts_count_(0), + entered_context_count_during_microtasks_(0), +#ifdef DEBUG + debug_microtasks_depth_(0), +#endif + microtasks_policy_(v8::MicrotasksPolicy::kAuto), + last_handle_before_deferred_block_(nullptr) { + } + + ~HandleScopeImplementer() { + DeleteArray(spare_); + } + + // Threading support for handle data. + static int ArchiveSpacePerThread(); + char* RestoreThread(char* from); + char* ArchiveThread(char* to); + void FreeThreadResources(); + + // Garbage collection support. + void Iterate(v8::internal::RootVisitor* v); + static char* Iterate(v8::internal::RootVisitor* v, char* data); + + inline internal::Object** GetSpareOrNewBlock(); + inline void DeleteExtensions(internal::Object** prev_limit); + + // Call depth represents nested v8 api calls. + inline void IncrementCallDepth() {call_depth_++;} + inline void DecrementCallDepth() {call_depth_--;} + inline bool CallDepthIsZero() { return call_depth_ == 0; } + + // Microtasks scope depth represents nested scopes controlling microtasks + // invocation, which happens when depth reaches zero. + inline void IncrementMicrotasksScopeDepth() {microtasks_depth_++;} + inline void DecrementMicrotasksScopeDepth() {microtasks_depth_--;} + inline int GetMicrotasksScopeDepth() { return microtasks_depth_; } + + // Possibly nested microtasks suppression scopes prevent microtasks + // from running. + inline void IncrementMicrotasksSuppressions() {microtasks_suppressions_++;} + inline void DecrementMicrotasksSuppressions() {microtasks_suppressions_--;} + inline bool HasMicrotasksSuppressions() { return !!microtasks_suppressions_; } + +#ifdef DEBUG + // In debug we check that calls not intended to invoke microtasks are + // still correctly wrapped with microtask scopes. + inline void IncrementDebugMicrotasksScopeDepth() {debug_microtasks_depth_++;} + inline void DecrementDebugMicrotasksScopeDepth() {debug_microtasks_depth_--;} + inline bool DebugMicrotasksScopeDepthIsZero() { + return debug_microtasks_depth_ == 0; + } +#endif + + inline void set_microtasks_policy(v8::MicrotasksPolicy policy); + inline v8::MicrotasksPolicy microtasks_policy() const; + + inline void EnterContext(Handle context); + inline void LeaveContext(); + inline bool LastEnteredContextWas(Handle context); + + // Returns the last entered context or an empty handle if no + // contexts have been entered. + inline Handle LastEnteredContext(); + + inline void EnterMicrotaskContext(Handle context); + inline void LeaveMicrotaskContext(); + inline Handle MicrotaskContext(); + inline bool MicrotaskContextIsLastEnteredContext() const { + return microtask_context_ && + entered_context_count_during_microtasks_ == entered_contexts_.size(); + } + + inline void SaveContext(Context* context); + inline Context* RestoreContext(); + inline bool HasSavedContexts(); + + inline DetachableVector* blocks() { return &blocks_; } + Isolate* isolate() const { return isolate_; } + + void ReturnBlock(Object** block) { + DCHECK_NOT_NULL(block); + if (spare_ != nullptr) DeleteArray(spare_); + spare_ = block; + } + + private: + void ResetAfterArchive() { + blocks_.detach(); + entered_contexts_.detach(); + saved_contexts_.detach(); + microtask_context_ = nullptr; + entered_context_count_during_microtasks_ = 0; + spare_ = nullptr; + last_handle_before_deferred_block_ = nullptr; + call_depth_ = 0; + } + + void Free() { + DCHECK(blocks_.empty()); + DCHECK(entered_contexts_.empty()); + DCHECK(saved_contexts_.empty()); + DCHECK(!microtask_context_); + + blocks_.free(); + entered_contexts_.free(); + saved_contexts_.free(); + if (spare_ != nullptr) { + DeleteArray(spare_); + spare_ = nullptr; + } + DCHECK_EQ(call_depth_, 0); + } + + void BeginDeferredScope(); + DeferredHandles* Detach(Object** prev_limit); + + Isolate* isolate_; + DetachableVector blocks_; + // Used as a stack to keep track of entered contexts. + DetachableVector entered_contexts_; + // Used as a stack to keep track of saved contexts. + DetachableVector saved_contexts_; + Context* microtask_context_; + Object** spare_; + int call_depth_; + int microtasks_depth_; + int microtasks_suppressions_; + size_t entered_contexts_count_; + size_t entered_context_count_during_microtasks_; +#ifdef DEBUG + int debug_microtasks_depth_; +#endif + v8::MicrotasksPolicy microtasks_policy_; + Object** last_handle_before_deferred_block_; + // This is only used for threading support. + HandleScopeData handle_scope_data_; + + void IterateThis(RootVisitor* v); + char* RestoreThreadHelper(char* from); + char* ArchiveThreadHelper(char* to); + + friend class DeferredHandles; + friend class DeferredHandleScope; + friend class HandleScopeImplementerOffsets; + + DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer); +}; + +class HandleScopeImplementerOffsets { + public: + enum Offsets { + kMicrotaskContext = offsetof(HandleScopeImplementer, microtask_context_), + kEnteredContexts = offsetof(HandleScopeImplementer, entered_contexts_), + kEnteredContextsCount = + offsetof(HandleScopeImplementer, entered_contexts_count_), + kEnteredContextCountDuringMicrotasks = offsetof( + HandleScopeImplementer, entered_context_count_during_microtasks_) + }; + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(HandleScopeImplementerOffsets); +}; + +const int kHandleBlockSize = v8::internal::KB - 2; // fit in one page + + +void HandleScopeImplementer::set_microtasks_policy( + v8::MicrotasksPolicy policy) { + microtasks_policy_ = policy; +} + + +v8::MicrotasksPolicy HandleScopeImplementer::microtasks_policy() const { + return microtasks_policy_; +} + + +void HandleScopeImplementer::SaveContext(Context* context) { + saved_contexts_.push_back(context); +} + + +Context* HandleScopeImplementer::RestoreContext() { + Context* last_context = saved_contexts_.back(); + saved_contexts_.pop_back(); + return last_context; +} + + +bool HandleScopeImplementer::HasSavedContexts() { + return !saved_contexts_.empty(); +} + + +void HandleScopeImplementer::EnterContext(Handle context) { + entered_contexts_.push_back(*context); + entered_contexts_count_ = entered_contexts_.size(); +} + +void HandleScopeImplementer::LeaveContext() { + entered_contexts_.pop_back(); + entered_contexts_count_ = entered_contexts_.size(); +} + +bool HandleScopeImplementer::LastEnteredContextWas(Handle context) { + return !entered_contexts_.empty() && entered_contexts_.back() == *context; +} + +void HandleScopeImplementer::EnterMicrotaskContext(Handle context) { + DCHECK(!microtask_context_); + microtask_context_ = *context; + entered_context_count_during_microtasks_ = entered_contexts_.size(); +} + +void HandleScopeImplementer::LeaveMicrotaskContext() { + microtask_context_ = nullptr; + entered_context_count_during_microtasks_ = 0; +} + +// If there's a spare block, use it for growing the current scope. +internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() { + internal::Object** block = + (spare_ != nullptr) ? spare_ + : NewArray(kHandleBlockSize); + spare_ = nullptr; + return block; +} + + +void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) { + while (!blocks_.empty()) { + internal::Object** block_start = blocks_.back(); + internal::Object** block_limit = block_start + kHandleBlockSize; + + // SealHandleScope may make the prev_limit to point inside the block. + if (block_start <= prev_limit && prev_limit <= block_limit) { +#ifdef ENABLE_HANDLE_ZAPPING + internal::HandleScope::ZapRange(prev_limit, block_limit); +#endif + break; + } + + blocks_.pop_back(); +#ifdef ENABLE_HANDLE_ZAPPING + internal::HandleScope::ZapRange(block_start, block_limit); +#endif + if (spare_ != nullptr) { + DeleteArray(spare_); + } + spare_ = block_start; + } + DCHECK((blocks_.empty() && prev_limit == nullptr) || + (!blocks_.empty() && prev_limit != nullptr)); +} + +// Interceptor functions called from generated inline caches to notify +// CPU profiler that external callbacks are invoked. +void InvokeAccessorGetterCallback( + v8::Local property, + const v8::PropertyCallbackInfo& info, + v8::AccessorNameGetterCallback getter); + +void InvokeFunctionCallback(const v8::FunctionCallbackInfo& info, + v8::FunctionCallback callback); + +class Testing { + public: + static v8::Testing::StressType stress_type() { return stress_type_; } + static void set_stress_type(v8::Testing::StressType stress_type) { + stress_type_ = stress_type; + } + + private: + static v8::Testing::StressType stress_type_; +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_API_H_ diff --git a/demo/cplusplus-source.cc b/demo/cplusplus-source.cc new file mode 100644 index 0000000..00543ea --- /dev/null +++ b/demo/cplusplus-source.cc @@ -0,0 +1,10714 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/api.h" + +#include // For memcpy, strlen. +#include // For isnan. +#include +#include + +#include "src/api-inl.h" + +#include "include/v8-profiler.h" +#include "include/v8-testing.h" +#include "include/v8-util.h" +#include "src/accessors.h" +#include "src/api-natives.h" +#include "src/assert-scope.h" +#include "src/base/functional.h" +#include "src/base/logging.h" +#include "src/base/platform/platform.h" +#include "src/base/platform/time.h" +#include "src/base/safe_conversions.h" +#include "src/base/utils/random-number-generator.h" +#include "src/bootstrapper.h" +#include "src/builtins/builtins-utils.h" +#include "src/char-predicates-inl.h" +#include "src/code-stubs.h" +#include "src/compiler-dispatcher/compiler-dispatcher.h" +#include "src/compiler.h" +#include "src/contexts.h" +#include "src/conversions-inl.h" +#include "src/counters.h" +#include "src/debug/debug-coverage.h" +#include "src/debug/debug-evaluate.h" +#include "src/debug/debug-type-profile.h" +#include "src/debug/debug.h" +#include "src/debug/liveedit.h" +#include "src/deoptimizer.h" +#include "src/detachable-vector.h" +#include "src/execution.h" +#include "src/frames-inl.h" +#include "src/gdb-jit.h" +#include "src/global-handles.h" +#include "src/globals.h" +#include "src/icu_util.h" +#include "src/isolate-inl.h" +#include "src/json-parser.h" +#include "src/json-stringifier.h" +#include "src/messages.h" +#include "src/objects-inl.h" +#include "src/objects/api-callbacks.h" +#include "src/objects/js-array-inl.h" +#include "src/objects/js-collection-inl.h" +#include "src/objects/js-generator-inl.h" +#include "src/objects/js-promise-inl.h" +#include "src/objects/js-regexp-inl.h" +#include "src/objects/module-inl.h" +#include "src/objects/ordered-hash-table-inl.h" +#include "src/objects/slots.h" +#include "src/objects/stack-frame-info-inl.h" +#include "src/objects/templates.h" +#include "src/parsing/parse-info.h" +#include "src/parsing/parser.h" +#include "src/parsing/scanner-character-streams.h" +#include "src/pending-compilation-error-handler.h" +#include "src/profiler/cpu-profiler.h" +#include "src/profiler/heap-profiler.h" +#include "src/profiler/heap-snapshot-generator-inl.h" +#include "src/profiler/profile-generator-inl.h" +#include "src/profiler/tick-sample.h" +#include "src/property-descriptor.h" +#include "src/property-details.h" +#include "src/property.h" +#include "src/prototype.h" +#include "src/runtime-profiler.h" +#include "src/runtime/runtime.h" +#include "src/simulator.h" +#include "src/snapshot/builtin-serializer.h" +#include "src/snapshot/code-serializer.h" +#include "src/snapshot/natives.h" +#include "src/snapshot/partial-serializer.h" +#include "src/snapshot/read-only-serializer.h" +#include "src/snapshot/snapshot.h" +#include "src/snapshot/startup-serializer.h" +#include "src/startup-data-util.h" +#include "src/string-hasher.h" +#include "src/tracing/trace-event.h" +#include "src/trap-handler/trap-handler.h" +#include "src/unicode-cache-inl.h" +#include "src/unicode-inl.h" +#include "src/v8.h" +#include "src/v8threads.h" +#include "src/value-serializer.h" +#include "src/version.h" +#include "src/vm-state-inl.h" +#include "src/wasm/streaming-decoder.h" +#include "src/wasm/wasm-engine.h" +#include "src/wasm/wasm-objects-inl.h" +#include "src/wasm/wasm-result.h" +#include "src/wasm/wasm-serialization.h" + +namespace v8 { + +/* + * Most API methods should use one of the three macros: + * + * ENTER_V8, ENTER_V8_NO_SCRIPT, ENTER_V8_NO_SCRIPT_NO_EXCEPTION. + * + * The latter two assume that no script is executed, and no exceptions are + * scheduled in addition (respectively). Creating a pending exception and + * removing it before returning is ok. + * + * Exceptions should be handled either by invoking one of the + * RETURN_ON_FAILED_EXECUTION* macros. + * + * Don't use macros with DO_NOT_USE in their name. + * + * TODO(jochen): Document debugger specific macros. + * TODO(jochen): Document LOG_API and other RuntimeCallStats macros. + * TODO(jochen): All API methods should invoke one of the ENTER_V8* macros. + * TODO(jochen): Remove calls form API methods to DO_NOT_USE macros. + */ + +#define LOG_API(isolate, class_name, function_name) \ + i::RuntimeCallTimerScope _runtime_timer( \ + isolate, i::RuntimeCallCounterId::kAPI_##class_name##_##function_name); \ + LOG(isolate, ApiEntryCall("v8::" #class_name "::" #function_name)) + +#define ENTER_V8_DO_NOT_USE(isolate) i::VMState __state__((isolate)) + +#define ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, \ + function_name, bailout_value, \ + HandleScopeClass, do_callback) \ + if (IsExecutionTerminatingCheck(isolate)) { \ + return bailout_value; \ + } \ + HandleScopeClass handle_scope(isolate); \ + CallDepthScope call_depth_scope(isolate, context); \ + LOG_API(isolate, class_name, function_name); \ + i::VMState __state__((isolate)); \ + bool has_pending_exception = false + +#define PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, T) \ + if (IsExecutionTerminatingCheck(isolate)) { \ + return MaybeLocal(); \ + } \ + InternalEscapableScope handle_scope(isolate); \ + CallDepthScope call_depth_scope(isolate, v8::Local()); \ + i::VMState __state__((isolate)); \ + bool has_pending_exception = false + +#define PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ + bailout_value, HandleScopeClass, \ + do_callback) \ + auto isolate = context.IsEmpty() \ + ? i::Isolate::Current() \ + : reinterpret_cast(context->GetIsolate()); \ + ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \ + bailout_value, HandleScopeClass, do_callback); + +#define PREPARE_FOR_EXECUTION(context, class_name, function_name, T) \ + PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ + MaybeLocal(), InternalEscapableScope, \ + false) + +#define ENTER_V8(isolate, context, class_name, function_name, bailout_value, \ + HandleScopeClass) \ + ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \ + bailout_value, HandleScopeClass, true) + +#ifdef DEBUG +#define ENTER_V8_NO_SCRIPT(isolate, context, class_name, function_name, \ + bailout_value, HandleScopeClass) \ + ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \ + bailout_value, HandleScopeClass, false); \ + i::DisallowJavascriptExecutionDebugOnly __no_script__((isolate)) + +#define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate) \ + i::VMState __state__((isolate)); \ + i::DisallowJavascriptExecutionDebugOnly __no_script__((isolate)); \ + i::DisallowExceptions __no_exceptions__((isolate)) + +#define ENTER_V8_FOR_NEW_CONTEXT(isolate) \ + i::VMState __state__((isolate)); \ + i::DisallowExceptions __no_exceptions__((isolate)) +#else +#define ENTER_V8_NO_SCRIPT(isolate, context, class_name, function_name, \ + bailout_value, HandleScopeClass) \ + ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \ + bailout_value, HandleScopeClass, false) + +#define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate) \ + i::VMState __state__((isolate)); + +#define ENTER_V8_FOR_NEW_CONTEXT(isolate) \ + i::VMState __state__((isolate)); +#endif // DEBUG + +#define EXCEPTION_BAILOUT_CHECK_SCOPED_DO_NOT_USE(isolate, value) \ + do { \ + if (has_pending_exception) { \ + call_depth_scope.Escape(); \ + return value; \ + } \ + } while (false) + +#define RETURN_ON_FAILED_EXECUTION(T) \ + EXCEPTION_BAILOUT_CHECK_SCOPED_DO_NOT_USE(isolate, MaybeLocal()) + +#define RETURN_ON_FAILED_EXECUTION_PRIMITIVE(T) \ + EXCEPTION_BAILOUT_CHECK_SCOPED_DO_NOT_USE(isolate, Nothing()) + +#define RETURN_TO_LOCAL_UNCHECKED(maybe_local, T) \ + return maybe_local.FromMaybe(Local()); + + +#define RETURN_ESCAPED(value) return handle_scope.Escape(value); + +namespace { + +Local ContextFromNeverReadOnlySpaceObject( + i::Handle obj) { + return reinterpret_cast(obj->GetIsolate())->GetCurrentContext(); +} + +class InternalEscapableScope : public v8::EscapableHandleScope { + public: + explicit inline InternalEscapableScope(i::Isolate* isolate) + : v8::EscapableHandleScope(reinterpret_cast(isolate)) {} +}; + +// TODO(jochen): This should be #ifdef DEBUG +#ifdef V8_CHECK_MICROTASKS_SCOPES_CONSISTENCY +void CheckMicrotasksScopesConsistency(i::Isolate* isolate) { + auto handle_scope_implementer = isolate->handle_scope_implementer(); + if (handle_scope_implementer->microtasks_policy() == + v8::MicrotasksPolicy::kScoped) { + DCHECK(handle_scope_implementer->GetMicrotasksScopeDepth() || + !handle_scope_implementer->DebugMicrotasksScopeDepthIsZero()); + } +} +#endif + +template +class CallDepthScope { + public: + explicit CallDepthScope(i::Isolate* isolate, Local context) + : isolate_(isolate), + context_(context), + escaped_(false), + safe_for_termination_(isolate->next_v8_call_is_safe_for_termination()), + interrupts_scope_(isolate_, i::StackGuard::TERMINATE_EXECUTION, + isolate_->only_terminate_in_safe_scope() + ? (safe_for_termination_ + ? i::InterruptsScope::kRunInterrupts + : i::InterruptsScope::kPostponeInterrupts) + : i::InterruptsScope::kNoop) { + // TODO(dcarney): remove this when blink stops crashing. + DCHECK(!isolate_->external_caught_exception()); + isolate_->handle_scope_implementer()->IncrementCallDepth(); + isolate_->set_next_v8_call_is_safe_for_termination(false); + if (!context.IsEmpty()) { + i::Handle env = Utils::OpenHandle(*context); + i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); + if (isolate->context() != nullptr && + isolate->context()->native_context() == env->native_context()) { + context_ = Local(); + } else { + impl->SaveContext(isolate->context()); + isolate->set_context(*env); + } + } + if (do_callback) isolate_->FireBeforeCallEnteredCallback(); + } + ~CallDepthScope() { + if (!context_.IsEmpty()) { + i::HandleScopeImplementer* impl = isolate_->handle_scope_implementer(); + isolate_->set_context(impl->RestoreContext()); + } + if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth(); + if (do_callback) isolate_->FireCallCompletedCallback(); +// TODO(jochen): This should be #ifdef DEBUG +#ifdef V8_CHECK_MICROTASKS_SCOPES_CONSISTENCY + if (do_callback) CheckMicrotasksScopesConsistency(isolate_); +#endif + isolate_->set_next_v8_call_is_safe_for_termination(safe_for_termination_); + } + + void Escape() { + DCHECK(!escaped_); + escaped_ = true; + auto handle_scope_implementer = isolate_->handle_scope_implementer(); + handle_scope_implementer->DecrementCallDepth(); + bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); + isolate_->OptionalRescheduleException(call_depth_is_zero); + } + + private: + i::Isolate* const isolate_; + Local context_; + bool escaped_; + bool do_callback_; + bool safe_for_termination_; + i::InterruptsScope interrupts_scope_; +}; + +} // namespace + + +static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate, + i::Handle script) { + i::Handle scriptName(script->GetNameOrSourceURL(), isolate); + i::Handle source_map_url(script->source_mapping_url(), isolate); + i::Handle host_defined_options(script->host_defined_options(), + isolate); + v8::Isolate* v8_isolate = reinterpret_cast(isolate); + ScriptOriginOptions options(script->origin_options()); + v8::ScriptOrigin origin( + Utils::ToLocal(scriptName), + v8::Integer::New(v8_isolate, script->line_offset()), + v8::Integer::New(v8_isolate, script->column_offset()), + v8::Boolean::New(v8_isolate, options.IsSharedCrossOrigin()), + v8::Integer::New(v8_isolate, script->id()), + Utils::ToLocal(source_map_url), + v8::Boolean::New(v8_isolate, options.IsOpaque()), + v8::Boolean::New(v8_isolate, script->type() == i::Script::TYPE_WASM), + v8::Boolean::New(v8_isolate, options.IsModule()), + Utils::ToLocal(host_defined_options)); + return origin; +} + + +// --- E x c e p t i o n B e h a v i o r --- + +void i::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location) { + i::V8::FatalProcessOutOfMemory(isolate, location, false); +} + +// When V8 cannot allocate memory FatalProcessOutOfMemory is called. The default +// OOM error handler is called and execution is stopped. +void i::V8::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location, + bool is_heap_oom) { + char last_few_messages[Heap::kTraceRingBufferSize + 1]; + char js_stacktrace[Heap::kStacktraceBufferSize + 1]; + i::HeapStats heap_stats; + + if (isolate == nullptr) { + isolate = Isolate::Current(); + } + + if (isolate == nullptr) { + // On a background thread -> we cannot retrieve memory information from the + // Isolate. Write easy-to-recognize values on the stack. + memset(last_few_messages, 0x0BADC0DE, Heap::kTraceRingBufferSize + 1); + memset(js_stacktrace, 0x0BADC0DE, Heap::kStacktraceBufferSize + 1); + memset(&heap_stats, 0xBADC0DE, sizeof(heap_stats)); + // Note that the embedder's oom handler won't be called in this case. We + // just crash. + FATAL( + "API fatal error handler returned after process out of memory on the " + "background thread"); + UNREACHABLE(); + } + + memset(last_few_messages, 0, Heap::kTraceRingBufferSize + 1); + memset(js_stacktrace, 0, Heap::kStacktraceBufferSize + 1); + + intptr_t start_marker; + heap_stats.start_marker = &start_marker; + size_t ro_space_size; + heap_stats.ro_space_size = &ro_space_size; + size_t ro_space_capacity; + heap_stats.ro_space_capacity = &ro_space_capacity; + size_t new_space_size; + heap_stats.new_space_size = &new_space_size; + size_t new_space_capacity; + heap_stats.new_space_capacity = &new_space_capacity; + size_t old_space_size; + heap_stats.old_space_size = &old_space_size; + size_t old_space_capacity; + heap_stats.old_space_capacity = &old_space_capacity; + size_t code_space_size; + heap_stats.code_space_size = &code_space_size; + size_t code_space_capacity; + heap_stats.code_space_capacity = &code_space_capacity; + size_t map_space_size; + heap_stats.map_space_size = &map_space_size; + size_t map_space_capacity; + heap_stats.map_space_capacity = &map_space_capacity; + size_t lo_space_size; + heap_stats.lo_space_size = &lo_space_size; + size_t global_handle_count; + heap_stats.global_handle_count = &global_handle_count; + size_t weak_global_handle_count; + heap_stats.weak_global_handle_count = &weak_global_handle_count; + size_t pending_global_handle_count; + heap_stats.pending_global_handle_count = &pending_global_handle_count; + size_t near_death_global_handle_count; + heap_stats.near_death_global_handle_count = &near_death_global_handle_count; + size_t free_global_handle_count; + heap_stats.free_global_handle_count = &free_global_handle_count; + size_t memory_allocator_size; + heap_stats.memory_allocator_size = &memory_allocator_size; + size_t memory_allocator_capacity; + heap_stats.memory_allocator_capacity = &memory_allocator_capacity; + size_t malloced_memory; + heap_stats.malloced_memory = &malloced_memory; + size_t malloced_peak_memory; + heap_stats.malloced_peak_memory = &malloced_peak_memory; + size_t objects_per_type[LAST_TYPE + 1] = {0}; + heap_stats.objects_per_type = objects_per_type; + size_t size_per_type[LAST_TYPE + 1] = {0}; + heap_stats.size_per_type = size_per_type; + int os_error; + heap_stats.os_error = &os_error; + heap_stats.last_few_messages = last_few_messages; + heap_stats.js_stacktrace = js_stacktrace; + intptr_t end_marker; + heap_stats.end_marker = &end_marker; + if (isolate->heap()->HasBeenSetUp()) { + // BUG(1718): Don't use the take_snapshot since we don't support + // HeapIterator here without doing a special GC. + isolate->heap()->RecordStats(&heap_stats, false); + char* first_newline = strchr(last_few_messages, '\n'); + if (first_newline == nullptr || first_newline[1] == '\0') + first_newline = last_few_messages; + PrintF("\n<--- Last few GCs --->\n%s\n", first_newline); + PrintF("\n<--- JS stacktrace --->\n%s\n", js_stacktrace); + } + Utils::ReportOOMFailure(isolate, location, is_heap_oom); + // If the fatal error handler returns, we stop execution. + FATAL("API fatal error handler returned after process out of memory"); +} + + +void Utils::ReportApiFailure(const char* location, const char* message) { + i::Isolate* isolate = i::Isolate::Current(); + FatalErrorCallback callback = nullptr; + if (isolate != nullptr) { + callback = isolate->exception_behavior(); + } + if (callback == nullptr) { + base::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n", location, + message); + base::OS::Abort(); + } else { + callback(location, message); + } + isolate->SignalFatalError(); +} + +void Utils::ReportOOMFailure(i::Isolate* isolate, const char* location, + bool is_heap_oom) { + OOMErrorCallback oom_callback = isolate->oom_behavior(); + if (oom_callback == nullptr) { + // TODO(wfh): Remove this fallback once Blink is setting OOM handler. See + // crbug.com/614440. + FatalErrorCallback fatal_callback = isolate->exception_behavior(); + if (fatal_callback == nullptr) { + base::OS::PrintError("\n#\n# Fatal %s OOM in %s\n#\n\n", + is_heap_oom ? "javascript" : "process", location); + base::OS::Abort(); + } else { + fatal_callback(location, + is_heap_oom + ? "Allocation failed - JavaScript heap out of memory" + : "Allocation failed - process out of memory"); + } + } else { + oom_callback(location, is_heap_oom); + } + isolate->SignalFatalError(); +} + +static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { + if (isolate->has_scheduled_exception()) { + return isolate->scheduled_exception() == + i::ReadOnlyRoots(isolate).termination_exception(); + } + return false; +} + + +void V8::SetNativesDataBlob(StartupData* natives_blob) { + i::V8::SetNativesBlob(natives_blob); +} + + +void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) { + i::V8::SetSnapshotBlob(snapshot_blob); +} + +namespace { + +class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { + public: + void* Allocate(size_t length) override { +#if V8_OS_AIX && _LINUX_SOURCE_COMPAT + // Work around for GCC bug on AIX + // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839 + void* data = __linux_calloc(length, 1); +#else + void* data = calloc(length, 1); +#endif + return data; + } + + void* AllocateUninitialized(size_t length) override { +#if V8_OS_AIX && _LINUX_SOURCE_COMPAT + // Work around for GCC bug on AIX + // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839 + void* data = __linux_malloc(length); +#else + void* data = malloc(length); +#endif + return data; + } + + void Free(void* data, size_t) override { free(data); } +}; + +struct SnapshotCreatorData { + explicit SnapshotCreatorData(Isolate* isolate) + : isolate_(isolate), + default_context_(), + contexts_(isolate), + created_(false) {} + + static SnapshotCreatorData* cast(void* data) { + return reinterpret_cast(data); + } + + ArrayBufferAllocator allocator_; + Isolate* isolate_; + Persistent default_context_; + SerializeInternalFieldsCallback default_embedder_fields_serializer_; + PersistentValueVector contexts_; + std::vector embedder_fields_serializers_; + bool created_; +}; + +} // namespace + +SnapshotCreator::SnapshotCreator(Isolate* isolate, + const intptr_t* external_references, + StartupData* existing_snapshot) { + SnapshotCreatorData* data = new SnapshotCreatorData(isolate); + data->isolate_ = isolate; + i::Isolate* internal_isolate = reinterpret_cast(isolate); + internal_isolate->set_array_buffer_allocator(&data->allocator_); + internal_isolate->set_api_external_references(external_references); + internal_isolate->enable_serializer(); + isolate->Enter(); + const StartupData* blob = existing_snapshot + ? existing_snapshot + : i::Snapshot::DefaultSnapshotBlob(); + if (blob && blob->raw_size > 0) { + internal_isolate->set_snapshot_blob(blob); + i::Snapshot::Initialize(internal_isolate); + } else { + internal_isolate->Init(nullptr); + } + data_ = data; +} + +SnapshotCreator::SnapshotCreator(const intptr_t* external_references, + StartupData* existing_snapshot) + : SnapshotCreator(reinterpret_cast(new i::Isolate()), + external_references, existing_snapshot) {} + +SnapshotCreator::~SnapshotCreator() { + SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); + DCHECK(data->created_); + Isolate* isolate = data->isolate_; + isolate->Exit(); + isolate->Dispose(); + delete data; +} + +Isolate* SnapshotCreator::GetIsolate() { + return SnapshotCreatorData::cast(data_)->isolate_; +} + +void SnapshotCreator::SetDefaultContext( + Local context, SerializeInternalFieldsCallback callback) { + DCHECK(!context.IsEmpty()); + SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); + DCHECK(!data->created_); + DCHECK(data->default_context_.IsEmpty()); + Isolate* isolate = data->isolate_; + CHECK_EQ(isolate, context->GetIsolate()); + data->default_context_.Reset(isolate, context); + data->default_embedder_fields_serializer_ = callback; +} + +size_t SnapshotCreator::AddContext(Local context, + SerializeInternalFieldsCallback callback) { + DCHECK(!context.IsEmpty()); + SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); + DCHECK(!data->created_); + Isolate* isolate = data->isolate_; + CHECK_EQ(isolate, context->GetIsolate()); + size_t index = data->contexts_.Size(); + data->contexts_.Append(context); + data->embedder_fields_serializers_.push_back(callback); + return index; +} + +size_t SnapshotCreator::AddTemplate(Local