diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 86abf4c51..000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,44 +0,0 @@ - - -## Please, provide the details below: - -### Did you verify this is a real problem by searching the [NativeScript Forum](http://forum.nativescript.org) and the [other open issues in this repo](https://github.com/NativeScript/nativescript/issues)? - -### Tell us about the problem - - -### Please provide the following version numbers that your issue occurs with: - - -### Did the error happen while the app was being constructed? (buildtime error) - - -### Did the error happen while the app was executing? (runtime error) - - -### Please tell us how to recreate the issue in as much detail as possible. - -Consider using the [playground](https://play.nativescript.org) to provide the code you have issues with. - diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..6bf44d219 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,29 @@ +--- +name: Bug report +about: 'We really appreciate your effort to provide feedback. Before opening a new + issue, please make sure that this case is not already reported in GitHub as an + issue or in StackOverflow as a question.' + +--- + +**Environment** +Provide version numbers for the following components (information can be retrieved by running `tns info` in your project folder or by inspecting the `package.json` of the project): + - CLI: + - Cross-platform modules: + - Android Runtime: + - iOS Runtime (if applicable): + - Plugin(s): + +**Describe the bug** + + +**To Reproduce** + + +**Expected behavior** + +**Sample project** + + +**Additional context** + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..13358ad27 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** + + +**Describe the solution you'd like** + + +**Describe alternatives you've considered** + + +**Additional context** + diff --git a/CHANGELOG.md b/CHANGELOG.md index 130bb2255..6f60f9c18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +5.0.0 +== + +## What's New +- [Upgrade v8 to 6.9.427.23(#1168)](https://github.com/NativeScript/android-runtime/issues/1168) +- [Added support for before-plugins.gradle file applied before plugin(#1183)](https://github.com/NativeScript/android-runtime/pull/1185) +- [Make JSParser in SBG fail the build when failing(#1152)](https://github.com/NativeScript/android-runtime/issues/1152) +- [Generate interface names list in SBG in parallel(#1132)](https://github.com/NativeScript/android-runtime/issues/1132) +- [Upgrade android gradle plugin to 3.2.0(#1147)](https://github.com/NativeScript/android-runtime/issues/1147) + +## Bug Fixes + + - [Static Binding Generator fails if class has static properties that are used within the class(#1160)](https://github.com/NativeScript/android-runtime/issues/1160) + - [Fixing NoClassDefFoundError when using older API(#1164)](https://github.com/NativeScript/android-runtime/pull/1164) + 4.2.0 == diff --git a/README.md b/README.md index 53f400b3f..60a0727b8 100644 --- a/README.md +++ b/README.md @@ -96,4 +96,4 @@ We love PRs! Check out the [contributing guidelines](CONTRIBUTING.md). If you wa * [Implementing additional Chrome DevTools protocol Domains](docs/extending-inspector.md) ## Get Help -Please, use [github issues](https://github.com/NativeScript/android-runtime/issues) strictly for [reporting bugs](CONTRIBUTING.md#reporting-bugs) or [requesting features](CONTRIBUTING.md#requesting-new-features). For general questions and support, check out the [NativeScript community forum](https://discourse.nativescript.org/) or ask our experts in [NativeScript community Slack channel](http://developer.telerik.com/wp-login.php?action=slack-invitation). +Please, use [github issues](https://github.com/NativeScript/android-runtime/issues) strictly for [reporting bugs](CONTRIBUTING.md#reporting-bugs) or [requesting features](CONTRIBUTING.md#requesting-new-features). For general questions and support, check out [Stack Overflow](https://stackoverflow.com/questions/tagged/nativescript) or ask our experts in [NativeScript community Slack channel](http://developer.telerik.com/wp-login.php?action=slack-invitation). diff --git a/build-artifacts/project-template-gradle/settings.json b/build-artifacts/project-template-gradle/settings.json index 36c44b586..0e44c524d 100644 --- a/build-artifacts/project-template-gradle/settings.json +++ b/build-artifacts/project-template-gradle/settings.json @@ -1,3 +1,3 @@ { - "v8Version": "6.7.288.46" + "v8Version": "6.9.427.23" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 933b6473c..019065d1d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip diff --git a/package.json b/package.json index 71a943e22..092ed71fa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "tns-android", "description": "NativeScript Runtime for Android", - "version": "4.2.0", + "version": "5.0.0", "repository": { "type": "git", "url": "https://github.com/NativeScript/android-runtime.git" @@ -11,6 +11,6 @@ ], "gradle": { "version": "4.4", - "android": "3.1.3" + "android": "3.1.4" } } diff --git a/test-app/app/build.gradle b/test-app/app/build.gradle index 95d00844b..492553b8f 100644 --- a/test-app/app/build.gradle +++ b/test-app/app/build.gradle @@ -75,7 +75,7 @@ def nativescriptDependencies = new JsonSlurper().parseText(dependenciesJson.text def computeCompileSdkVersion = { -> project.hasProperty("compileSdk") ? compileSdk : 26 } def computeTargetSdkVersion = { -> project.hasProperty("targetSdk") ? targetSdk : 26 } def computeBuildToolsVersion = { -> - project.hasProperty("buildToolsVersion") ? buildToolsVersion : "27.0.3" + project.hasProperty("buildToolsVersion") ? buildToolsVersion : "28.0.2" } project.ext.selectedBuildType = project.hasProperty("release") ? "release" : "debug" @@ -111,7 +111,17 @@ def getAppResourcesPath = { -> project.ext.appResourcesPath = absolutePathToAppResources return absolutePathToAppResources -}; +} + +def applyBeforePluginGradleConfiguration = { -> + def appResourcesPath = getAppResourcesPath() + def pathToBeforePluginGradle = "$appResourcesPath/Android/before-plugins.gradle" + def beforePluginGradle = file(pathToBeforePluginGradle) + if (beforePluginGradle.exists()) { + println "\t + applying user-defined configuration from ${beforePluginGradle}" + apply from: pathToBeforePluginGradle + } +} def applyAppGradleConfiguration = { -> def appResourcesPath = getAppResourcesPath() @@ -212,8 +222,9 @@ android { } setAppIdentifier() - applyAppGradleConfiguration() + applyBeforePluginGradleConfiguration() applyPluginGradleConfigurations() + applyAppGradleConfiguration() } def externalRuntimeExists = !findProject(':runtime').is(null) @@ -251,6 +262,8 @@ dependencies { supportVer = supportVersion } + println "Using support library version $supportVer" + implementation "com.android.support:multidex:1.0.2" implementation "com.android.support:support-v4:$supportVer" implementation "com.android.support:appcompat-v7:$supportVer" @@ -477,14 +490,16 @@ task buildMetadata(type: JavaExec) { description "builds metadata with provided jar dependencies" inputs.files("$MDG_JAVA_DEPENDENCIES") - inputs.dir("$buildDir/intermediates/classes") + + def classesDir = "$buildDir/intermediates/javac" + inputs.dir(classesDir) outputs.files("$METADATA_OUT_PATH/treeNodeStream.dat", "$METADATA_OUT_PATH/treeStringsStream.dat", "$METADATA_OUT_PATH/treeValueStream.dat") doFirst { // get compiled classes to pass to metadata generator // these need to be called after the classes have compiled - def classesDir = "$buildDir/intermediates/classes" + assert file(classesDir).exists() def classesSubDirs = new File(classesDir).listFiles() def selectedBuildType = project.ext.selectedBuildType diff --git a/test-app/app/src/debug/java/com/tns/NativeScriptSyncServiceSocketImpl.java b/test-app/app/src/debug/java/com/tns/NativeScriptSyncServiceSocketImpl.java index 1e32dadda..c75d178c8 100644 --- a/test-app/app/src/debug/java/com/tns/NativeScriptSyncServiceSocketImpl.java +++ b/test-app/app/src/debug/java/com/tns/NativeScriptSyncServiceSocketImpl.java @@ -58,7 +58,6 @@ public void run() { deviceSystemSocket = new LocalServerSocket(this.name); while (running) { LocalSocket systemSocket = deviceSystemSocket.accept(); - systemSocket.setSoTimeout(70000); livesyncWorker = new LiveSyncWorker(systemSocket); Thread liveSyncThread = setUpLivesyncThread(); liveSyncThread.start(); @@ -116,7 +115,7 @@ private class LiveSyncWorker implements Runnable { public static final String FILE_CONTENT = "fileContent"; public static final String FILE_CONTENT_LENGTH = FILE_CONTENT + "Length"; public static final int DEFAULT_OPERATION = -1; - private static final String PROTOCOL_VERSION = "0.1.0"; + private static final String PROTOCOL_VERSION = "0.2.0"; private byte[] handshakeMessage; private final DigestInputStream input; private Closeable livesyncSocket; diff --git a/test-app/app/src/main/assets/app/modules/libCalc-arm.so b/test-app/app/src/main/assets/app/modules/libCalc-arm.so index 9da0a92f0..d5d3a4c5b 100755 Binary files a/test-app/app/src/main/assets/app/modules/libCalc-arm.so and b/test-app/app/src/main/assets/app/modules/libCalc-arm.so differ diff --git a/test-app/app/src/main/assets/app/modules/libCalc-arm64.so b/test-app/app/src/main/assets/app/modules/libCalc-arm64.so index 93350a38d..0101abdb7 100755 Binary files a/test-app/app/src/main/assets/app/modules/libCalc-arm64.so and b/test-app/app/src/main/assets/app/modules/libCalc-arm64.so differ diff --git a/test-app/app/src/main/assets/app/modules/libCalc-x86.so b/test-app/app/src/main/assets/app/modules/libCalc-x86.so index d71510551..078aa7233 100755 Binary files a/test-app/app/src/main/assets/app/modules/libCalc-x86.so and b/test-app/app/src/main/assets/app/modules/libCalc-x86.so differ diff --git a/test-app/app/src/main/assets/app/tests/testsWithContext.js b/test-app/app/src/main/assets/app/tests/testsWithContext.js index 0465c296e..958d12589 100644 --- a/test-app/app/src/main/assets/app/tests/testsWithContext.js +++ b/test-app/app/src/main/assets/app/tests/testsWithContext.js @@ -1,20 +1,20 @@ exports.run = function(cntxt) { describe("Tests with context ", function () { - + var context = cntxt; var myCustomEquality = function(first, second) { return first == second; }; - + beforeEach(function() { jasmine.addCustomEqualityTester(myCustomEquality); }); - + it("TestConstructorOverrideForBuiltinType", function () { - + __log("TEST: TestConstructorOverrideForBuiltinType"); - + var ctorCalled = false; var isConstructor = false; @@ -24,17 +24,17 @@ exports.run = function(cntxt) isConstructor = arguments[arguments.length - 1]; } }); - + var btn = new MyButton(context); - + expect(ctorCalled).toEqual(true); expect(isConstructor).toEqual(true); }); - + it("TestConstructorOverrideForBuiltinTypeWithInitMethod", function () { - + __log("TEST: TestConstructorOverrideForBuiltinTypeWithInitMethod"); - + var initInvocationCount = 0; var MyDatePicker = android.widget.DatePicker.extend({ @@ -42,30 +42,30 @@ exports.run = function(cntxt) ++initInvocationCount; } }); - + var datePicker = new MyDatePicker(context); - + __log("datePicker=" + datePicker); - + var count1 = initInvocationCount; - + expect(count1).toBeGreaterThan(0); - + datePicker.init(2014, 3, 25, null); - + var count2 = initInvocationCount; - + expect(count2).toBeGreaterThan(count1); }); - + it("TestBuiltinNestedClassCreation", function () { - + __log("TEST: TestBuiltinNestedClassCreation"); - + var loader = new android.content.Loader(context); var observer = new android.content.Loader.ForceLoadContentObserver(loader); - + expect(observer).not.toEqual(null); }); @@ -82,35 +82,47 @@ exports.run = function(cntxt) expect(exceptionCaught).toBe(true); }); - + it("TestPublicWindowManagerImplWithoutMetadata", function () { - + __log("TEST: TestPublicWindowManagerImplWithoutMetadata"); - + var windowManagerImpl = context.getSystemService(android.content.Context.WINDOW_SERVICE); - + var display = windowManagerImpl.getDefaultDisplay(); - + //__log("display.isValid=" + display.isValid()); - + var displayInfo = display.toString(); - + expect(displayInfo.length).toBeGreaterThan(0); }); - + it("TestCanPassCharSequenceArray", function () { - + __log("TEST: TestCanPassCharSequenceArray"); - + var alert = new android.app.AlertDialog.Builder(context); - + var builder = alert.setItems(["One", "Two" ], new android.content.DialogInterface.OnClickListener({ onClick: function (dialog, which) { // } })); - + expect(builder).not.toEqual(null); }); + + it("TestOldAPIForGettingMethodsListForMethodsWithParametersFromMissingType", function () { + __log("TEST: TestOldAPIForGettingMethodsListForMethodsWithParametersFromMissingType"); + + var til = new android.support.design.widget.TextInputLayout(context); + var editText = new android.widget.EditText(context); + var relativeLayout = new android.widget.RelativeLayout(context); + var relativeLayoutParams = new android.widget.RelativeLayout.LayoutParams(android.widget.RelativeLayout.LayoutParams.MATCH_PARENT, android.widget.RelativeLayout.LayoutParams.MATCH_PARENT); + relativeLayout.setLayoutParams(relativeLayoutParams); + editText.setHint("TEST"); + til.addView(editText); + }); }); }; \ No newline at end of file diff --git a/test-app/build-tools/android-metadata-generator/build.gradle b/test-app/build-tools/android-metadata-generator/build.gradle index 9820d6b05..13d5817b6 100644 --- a/test-app/build-tools/android-metadata-generator/build.gradle +++ b/test-app/build-tools/android-metadata-generator/build.gradle @@ -17,7 +17,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:3.1.4' } } diff --git a/test-app/build-tools/jsparser/tests/cases/decorated_double_assignment_ts/app/myCustomActivity.android.ts b/test-app/build-tools/jsparser/tests/cases/decorated_double_assignment_ts/app/myCustomActivity.android.ts new file mode 100644 index 000000000..b577da7d1 --- /dev/null +++ b/test-app/build-tools/jsparser/tests/cases/decorated_double_assignment_ts/app/myCustomActivity.android.ts @@ -0,0 +1,10 @@ +import Bundle = android.os.Bundle; + +@JavaProxy('org.nativescript.MyCustomActivity') +export class TestActivity extends android.app.Activity { + static readonly TEST1: string = "my_test"; + public onCreate(savedInstanceState?: Bundle): void { + super.onCreate(savedInstanceState); + console.log(TestActivity.TEST1); + } +} diff --git a/test-app/build-tools/jsparser/tests/cases/decorated_double_assignment_ts/app/myCustomActivity_ts.android.js b/test-app/build-tools/jsparser/tests/cases/decorated_double_assignment_ts/app/myCustomActivity_ts.android.js new file mode 100644 index 000000000..48bf750fb --- /dev/null +++ b/test-app/build-tools/jsparser/tests/cases/decorated_double_assignment_ts/app/myCustomActivity_ts.android.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var TestActivity = (function (_super) { + __extends(TestActivity, _super); + function TestActivity() { + return _super !== null && _super.apply(this, arguments) || this; + } + TestActivity_1 = TestActivity; + TestActivity.prototype.onCreate = function (savedInstanceState) { + _super.prototype.onCreate.call(this, savedInstanceState); + console.log(TestActivity_1.TEST1); + }; + var TestActivity_1; + TestActivity.TEST1 = "my_test"; + TestActivity = TestActivity_1 = __decorate([ + JavaProxy('org.nativescript.MyCustomActivity') + ], TestActivity); + return TestActivity; +}(android.app.Activity)); +exports.TestActivity = TestActivity; \ No newline at end of file diff --git a/test-app/build-tools/jsparser/tests/cases/decorated_double_assignment_ts/internal/ts_helpers.js b/test-app/build-tools/jsparser/tests/cases/decorated_double_assignment_ts/internal/ts_helpers.js new file mode 100644 index 000000000..2175f563f --- /dev/null +++ b/test-app/build-tools/jsparser/tests/cases/decorated_double_assignment_ts/internal/ts_helpers.js @@ -0,0 +1,124 @@ +(function() { + var __extends_ts = function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); + }; + + var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length; + var r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + + if (typeof global.Reflect === "object" && typeof global.Reflect.decorate === "function") { + r = global.Reflect.decorate(decorators, target, key, desc); + } + else { + for (var i = decorators.length - 1; i >= 0; i--) { + if (d = decorators[i]) { + r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + } + } + } + return c > 3 && r && Object.defineProperty(target, key, r), r; + }; + + var __native = function(thiz) { + var result = thiz.__proto__; + + for (var prop in thiz) + { + if (thiz.hasOwnProperty(prop)) + { + thiz.__proto__[prop] = thiz[prop]; + delete thiz[prop]; + } + } + + thiz.constructor = undefined; + thiz.__proto__ = undefined; + Object.freeze(thiz); + Object.preventExtensions(thiz) + return result; + }; + + var __extends = function(Child, Parent) { + + if (Parent.extend) { + if (Parent.__isPrototypeImplementationObject) { + throw new Error("Can not extend an already extended native object."); + } + + function extend(child, parent) { + __log("TS extend called"); + if (!child.__extended) { + child.__extended = parent.extend(child.name, child.prototype); + } + + return child.__extended; + }; + + Parent.__activityExtend = function(parent, name, implementationObject) { + __log("__activityExtend called"); + return parent.extend(name, implementationObject); + }; + + Parent.call = function(thiz) { + var Extended = extend(thiz.__proto__.__child, thiz.__proto__.__parent); + if (arguments.length > 1) + { + thiz.__proto__ = new (Function.prototype.bind.apply(Extended, [null].concat(Array.prototype.slice.call(arguments, 1)))); + } + else + { + thiz.__proto__ = new Extended(); + } + }; + + Parent.apply = function(thiz, args) { + var Extended = extend(thiz.__proto__.__child, thiz.__proto__.__parent); + if (args && args.length > 0) + { + thiz.__proto__ = new (Function.prototype.bind.apply(Extended, [null].concat(args))); + } + else + { + thiz.__proto__ = new Extended(); + } + }; + } + + __extends_ts(Child, Parent); + + + if (Parent.extend) { + Child.__isPrototypeImplementationObject = true; + Child.__proto__ = Parent; + Child.prototype.__parent = Parent; + Child.prototype.__child = Child; + } + } + + function JavaProxy(className) { + return function (target) { + var extended = target.extend(className, target.prototype) + extended.name = className; + return extended; + }; + } + + function Interfaces(interfacesArr) { + return function (target) { + if(interfacesArr instanceof Array) { + // attach interfaces: [] to the object + target.prototype.interfaces = interfacesArr; + } + } + } + + global.__native = __native; + global.__extends = __extends; + global.__decorate = __decorate; + global.JavaProxy = JavaProxy; + global.Interfaces = Interfaces; +})() \ No newline at end of file diff --git a/test-app/build-tools/jsparser/tests/specs/ast-parser-tests.spec.js b/test-app/build-tools/jsparser/tests/specs/ast-parser-tests.spec.js index 820b509a1..0684cd517 100644 --- a/test-app/build-tools/jsparser/tests/specs/ast-parser-tests.spec.js +++ b/test-app/build-tools/jsparser/tests/specs/ast-parser-tests.spec.js @@ -243,6 +243,42 @@ describe("parser/js_parser tests", function () { }); }); + it("Generated metadata for bindings should return proper JavaClass name when there is a static property and double assignment", function (done) { + let input = path.normalize(path.join(prefix, "decorated_double_assignment_ts", "app")), + generatedJavaClassesRoot = path.normalize(path.join(prefix, "decorated_double_assignment_ts", "src", "main", "java")); + + const newClassNames = [ + "org.nativescript.MyCustomActivity", + ]; + + clearOutput(); + + execGradle(input, generatedJavaClassesRoot, function (error, stdout, stderr) { + if (error) { + console.error(`exec error: ${error}`); + return; + } + + logExecResult(stdout, stderr) + + let bindingsContent = fs.readFileSync(sbgBindingOutoutFile, "utf-8").toString().trim().split('\n'); + + expect(bindingsContent.length).toBe(1); + + + for (let line of bindingsContent) { + var lineParts = line.split("*"); + var tsExtendsPart = lineParts[1]; + expect(tsExtendsPart).toBeFalsy(); + + var newClassNamePart = lineParts[6]; + expect(newClassNames).toContain(newClassNamePart); + } + + done(); + }); + }); + it("Generate valid metadata for bindings where multiple interfaces are implemented using array", function (done) { let input = path.normalize(path.join(prefix, "extends_with_interfaces", "app")); generatedJavaClassesRoot = path.normalize(path.join(prefix, "extends_with_interfaces", "src", "main", "java")); diff --git a/test-app/build-tools/jsparser/visitors/es5-visitors.js b/test-app/build-tools/jsparser/visitors/es5-visitors.js index fe7789b9e..bbeaa6366 100644 --- a/test-app/build-tools/jsparser/visitors/es5-visitors.js +++ b/test-app/build-tools/jsparser/visitors/es5-visitors.js @@ -1,4 +1,4 @@ -var es5_visitors = (function () { +var es5_visitors = (function() { var types = require("babel-types"), @@ -12,14 +12,14 @@ var es5_visitors = (function () { customExtendsArrGlobal = []; - /* ENTRY POINT! - * Traverses each passed node with several visitors. - * Result from visit can be got from static methods. - * - * Input parameters: - * path - node to visit - * config - filename, decorator name ... - */ + /* ENTRY POINT! + * Traverses each passed node with several visitors. + * Result from visit can be got from static methods. + * + * Input parameters: + * path - node to visit + * config - filename, decorator name ... + */ function es5Visitor(path, config) { if (!config.filePath) { @@ -31,7 +31,7 @@ var es5_visitors = (function () { } // ES5 Syntax - // anchor is extend (normal extend pattern + custom extend pattern) + // anchor is extend (normal extend pattern + custom extend pattern) if (types.isMemberExpression(path) && path.node.property.name === "extend") { traverseEs5Extend(path, config); } @@ -59,19 +59,19 @@ var es5_visitors = (function () { } - /* - * Returns the custom extends array generated from visitor - */ - es5Visitor.getProxyExtendInfo = function () { + /* + * Returns the custom extends array generated from visitor + */ + es5Visitor.getProxyExtendInfo = function() { var res = customExtendsArr.slice(); customExtendsArr = []; return res; } /* - * Returns the common extends array generated from visitor - */ - es5Visitor.getCommonExtendInfo = function () { + * Returns the common extends array generated from visitor + */ + es5Visitor.getCommonExtendInfo = function() { var res = []; for (var index in normalExtendsArr) { if (normalExtendsArr[index][0] !== "*") { @@ -83,19 +83,19 @@ var es5_visitors = (function () { return res; } - /* - * Returns the extended interfaces array generated from visitor - */ - es5Visitor.getInterfaceInfo = function () { + /* + * Returns the extended interfaces array generated from visitor + */ + es5Visitor.getInterfaceInfo = function() { var res = interfacesArr.slice(); interfacesArr = []; return res; } - /* - * Traverses the typescript extend case (__extends()) - * Write results in "normalExtendsArr" or "customExtendsArr". - */ + /* + * Traverses the typescript extend case (__extends()) + * Write results in "normalExtendsArr" or "customExtendsArr". + */ function traverseTsExtend(path, config) { // information for normal extend (unnamed) var extendClass; @@ -226,15 +226,15 @@ var es5_visitors = (function () { if possibleExpressionStatements[0].expression.right is logical expression if possibleExpressionStatements[0].expression.right.left is Call expression if possibleExpressionStatements[0].expression.right.left.callee.object.name === superVariableIdentifier - if the above is valid, then variableRHS = possibleVariableDeclarations[0].expression.right.left + if the above is valid, then variableRHS = possibleVariableDeclarations[0].expression.right.left */ function getThisAssignmentSuperCallLineNode(nodes, superIdentifier) { var matchingNodes = nodes.filter( (node) => { - return types.isAssignmentExpression(node.expression) - && types.isLogicalExpression(node.expression.right) - && types.isCallExpression(node.expression.right.left) - && node.expression.right.left.callee.object.name === superIdentifier; + return types.isAssignmentExpression(node.expression) && + types.isLogicalExpression(node.expression.right) && + types.isCallExpression(node.expression.right.left) && + node.expression.right.left.callee.object.name === superIdentifier; }); return matchingNodes.length > 0 ? matchingNodes[0].expression.right.left : null; @@ -250,9 +250,9 @@ var es5_visitors = (function () { function getThisDeclarationSuperCallLineNode(nodes, superIdentifier) { var matchingNodes = nodes.filter( (node) => { - return types.isLogicalExpression(node.declarations[0].init) - && types.isCallExpression(node.declarations[0].init.left) - && node.declarations[0].init.left.callee.object.name === superIdentifier; + return types.isLogicalExpression(node.declarations[0].init) && + types.isCallExpression(node.declarations[0].init.left) && + node.declarations[0].init.left.callee.object.name === superIdentifier; }); return matchingNodes.length > 0 ? matchingNodes[0].declarations[0].init.left : null; @@ -272,8 +272,8 @@ var es5_visitors = (function () { }); if (possibleVariableDeclarations.length > 0 || possibleExpressionStatements.length > 0) { - var superCallRHS = getThisDeclarationSuperCallLineNode(possibleVariableDeclarations, superVariableIdentifier) - || getThisAssignmentSuperCallLineNode(possibleExpressionStatements, superVariableIdentifier); + var superCallRHS = getThisDeclarationSuperCallLineNode(possibleVariableDeclarations, superVariableIdentifier) || + getThisAssignmentSuperCallLineNode(possibleExpressionStatements, superVariableIdentifier); if (superCallRHS) { var superCallee = superCallRHS.callee.property; @@ -304,7 +304,7 @@ var es5_visitors = (function () { if (isDecorateStatement(ci)) { // returns the node of the decorate (node.expression.right.callee) // __decorate([..]) - return ci.expression.right.arguments[0].elements; + return getRightExpression(ci.expression).arguments[0].elements; } } @@ -319,29 +319,42 @@ var es5_visitors = (function () { if (isDecorateStatement(sibling)) { // returns the node of the decorate (node.expression.right.callee) // __decorate([..]) - return sibling.expression.right.arguments[0].elements; + return getRightExpression(sibling.expression).arguments[0].elements; } } return null; } + function getRightExpression(expression) { + if(!expression) { + return null; + } + var rightExpression = expression.right; + // if the right expression is a new assignment, get the right expression from that assignment + while (types.isAssignmentExpression(rightExpression)) { + rightExpression = rightExpression.right; + } + return rightExpression; + } + function isDecorateStatement(node) { + var rightExpression = getRightExpression(node.expression); return types.isExpressionStatement(node) && types.isAssignmentExpression(node.expression) && - node.expression.right.callee && - node.expression.right.callee.name === "__decorate" && - node.expression.right.arguments && - types.isArrayExpression(node.expression.right.arguments[0]) + rightExpression.callee && + rightExpression.callee.name === "__decorate" && + rightExpression.arguments && + types.isArrayExpression(rightExpression.arguments[0]) } - /* - * Traverses the node, which is a "new" expression and find if it's a native interface or not. - * Write results in "interfacesArr". - */ + /* + * Traverses the node, which is a "new" expression and find if it's a native interface or not. + * Write results in "interfacesArr". + */ function traverseInterface(path, config) { if (!config.interfaceNames) { - throw "No interface names are provided! You can pass them in config.interfaceNames as an array!" + throw "JSParser Error: No interface names are provided! You can pass them in config.interfaceNames as an array!" } var o = path.node.callee, @@ -364,14 +377,12 @@ var es5_visitors = (function () { arg1; if (path.node.arguments.length === 1) { arg1 = path.node.arguments[0]; - } - else if (path.node.arguments.length === 2) { + } else if (path.node.arguments.length === 2) { arg0 = path.node.arguments[0]; arg1 = path.node.arguments[1]; - } - else { + } else { throw { - message: "Not enough or too many arguments passed(" + path.node.arguments.length + ") when trying to extend interface in file: " + config.filePath, + message: "JSParser Error: Not enough or too many arguments passed(" + path.node.arguments.length + ") when trying to extend interface: " + interfaceName + " in file: " + config.filePath, errCode: 1 } } @@ -393,16 +404,16 @@ var es5_visitors = (function () { } } - /* - * Finds the java proxy name from custom class decorator. - * Write results in "customExtendsArr" - */ + /* + * Finds the java proxy name from custom class decorator. + * Write results in "customExtendsArr" + */ function traverseJavaProxyExtend(path, config, customDecoratorName, extendClass, overriddenMethodNames, implementedInterfaces) { if (config.logger) { config.logger.info("\t+in " + customDecoratorName + " anchor"); } - var classNameFromDecorator = path;//_getDecoratorArgument(path, config, customDecoratorName); + var classNameFromDecorator = path; //_getDecoratorArgument(path, config, customDecoratorName); var lineToWrite = _generateLineToWrite(classNameFromDecorator, extendClass, overriddenMethodNames, "", config.fullPathName, implementedInterfaces); if (config.logger) { @@ -411,11 +422,11 @@ var es5_visitors = (function () { addCustomExtend(classNameFromDecorator, config.fullPathName, lineToWrite) } - /* - * Finds the normal extend name, overridden methods and possibly java proxy name from passed node. - * Writes to "customExtendsArr" or "normalExtendsArr". - * Left whole for readability. - */ + /* + * Finds the normal extend name, overridden methods and possibly java proxy name from passed node. + * Writes to "customExtendsArr" or "normalExtendsArr". + * Left whole for readability. + */ function traverseEs5Extend(path, config) { var callee = path.parent.callee; @@ -428,8 +439,7 @@ var es5_visitors = (function () { arg1; if (extendArguments.length === 1 && types.isObjectExpression(arg0)) { arg0 = extendArguments[0]; - } - else if (types.isStringLiteral(arg0)) { + } else if (types.isStringLiteral(arg0)) { } @@ -446,21 +456,19 @@ var es5_visitors = (function () { arg0 = extendArguments[0]; arg1 = extendArguments[1]; } - } - else { + } else { // don't throw here, because there can be a valid js extend that has nothing to do with NS return; throw { - message: "Not enough or too many arguments passed(" + extendArguments.length + ") when trying to extend class in file: " + config.filePath, + message: "JSParser Error: Not enough or too many arguments passed(" + extendArguments.length + ") when trying to extend class: " + extendClass + " in file: " + config.filePath, errCode: 1 } } - } - else { + } else { // don't throw here, because there can be a valid js extend that has nothing to do with NS return; throw { - message: "You need to call the extend with parameters. Example: '...extend(\"a.b.C\", {...overrides...})') in file: " + config.filePath, + message: "JSParser Error: You need to call the extend with parameters. Example: '...extend(\"a.b.C\", {...overrides...})') for class: " + extendClass + " in file: " + config.filePath, errCode: 1 } } @@ -476,7 +484,7 @@ var es5_visitors = (function () { var isCorrectClassName = _testClassName(className); if (className && !isCorrectClassName && !isCorrectExtendClassName) { throw { - message: "The 'extend' you are trying to make has an invalid name. Example: '...extend(\"a.b.C\", {...overrides...})'), file: " + config.filePath, + message: "JSParser Error: The 'extend' you are trying to make has an invalid name. Example: '...extend(\"a.b.C\", {...overrides...})'), for class: " + extendClass + " file: " + config.filePath, errCode: 1 } } @@ -505,20 +513,19 @@ var es5_visitors = (function () { }; lineToWrite = _generateLineToWrite(isCorrectExtendClassName ? className : "", extendClass.reverse().join("."), overriddenMethodNames, extendInfo, "", implementedInterfaces); normalExtendsArr.push(lineToWrite) - } - else { + } else { // don't throw here, because there can be a valid js extend that has nothing to do with NS return; throw { - message: "You need to call the extend '...extend(\"extend_name\", {...overrides...})'), file: " + config.filePath, + message: "JSParser Error: You need to call the extend '...extend(\"extend_name\", {...overrides...})'), for class: " + extendClass + " file: " + config.filePath, errCode: 1 } } } - /* - * HELPER METHODS - */ + /* + * HELPER METHODS + */ function _getOverriddenMethods(node, config) { var overriddenMethodNames = []; if (types.isObjectExpression(node)) { @@ -534,7 +541,7 @@ var es5_visitors = (function () { // NOTE: It's a near-identical method to _getOverridenMethods for optimisation reasons // we do not want to check for interfaces while creating an interface - // and likewise, we do not want to iterate twice through the impl. object's properties to read the interfaces + // and likewise, we do not want to iterate twice through the impl. object's properties to read the interfaces function _getOverridenMethodsAndImplementedInterfaces(node, config) { var result = []; var overriddenMethodNames = []; @@ -545,25 +552,25 @@ var es5_visitors = (function () { if (types.isObjectExpression(node)) { var objectProperties = node.properties; - /* - Iterates through all properties of the implementation object, e.g. - - { - method1: function() { - - }, - method3: function() { - - } - } - - will get 'method1' and 'method3' - */ + /* + Iterates through all properties of the implementation object, e.g. + + { + method1: function() { + + }, + method3: function() { + + } + } + + will get 'method1' and 'method3' + */ for (var index in objectProperties) { // if the user has declared interfaces that he is implementing - if (!interfacesFound - && objectProperties[index].key.name.toLowerCase() === "interfaces" - && types.isArrayExpression(objectProperties[index].value)) { + if (!interfacesFound && + objectProperties[index].key.name.toLowerCase() === "interfaces" && + types.isArrayExpression(objectProperties[index].value)) { interfacesFound = true; var interfaces = objectProperties[index].value.elements; @@ -638,10 +645,9 @@ var es5_visitors = (function () { if (extendedClass) { if (types.isCallExpression(extendedClass.node)) { var o = extendedClass.node.arguments[0]; - } - else { + } else { throw { - message: "Node type is not a call expression. File=" + config.filePath + " line=" + path.node.loc.start.line, + message: "JSParser Error: Node type is not a call expression. File=" + config.filePath + " line=" + path.node.loc.start.line, errCode: 1 } } @@ -661,24 +667,21 @@ var es5_visitors = (function () { var isCorrectExtendClassName = _testJavaProxyName(classNameFromDecorator); if (isCorrectExtendClassName) { return path.parent.arguments[0].value; - } - else { + } else { throw { - message: "The first argument '" + classNameFromDecorator + "' of the " + customDecoratorName + " decorator is not following the right pattern which is: '[namespace.]ClassName'. Example: '" + customDecoratorName + "(\"a.b.ClassName\", {overrides...})', file: " + config.filePath, + message: "JSParser Error: The first argument '" + classNameFromDecorator + "' of the " + customDecoratorName + " decorator is not following the right pattern which is: '[namespace.]ClassName'. Example: '" + customDecoratorName + "(\"a.b.ClassName\", {overrides...})', file: " + config.filePath, errCode: 1 } } - } - else { + } else { throw { - message: "No arguments passed to " + customDecoratorName + " decorator. Example: '" + customDecoratorName + "(\"a.b.ClassName\", {overrides...})', file: " + config.filePath, + message: "JSParser Error: No arguments passed to " + customDecoratorName + " decorator. Example: '" + customDecoratorName + "(\"a.b.ClassName\", {overrides...})', file: " + config.filePath, errCode: 1 } } - } - else { + } else { throw { - message: "Decorator " + customDecoratorName + " must be called with parameters: Example: '" + customDecoratorName + "(\"a.b.ClassName\", {overrides...})', file: " + config.filePath, + message: "JSParser Error: Decorator " + customDecoratorName + " must be called with parameters: Example: '" + customDecoratorName + "(\"a.b.ClassName\", {overrides...})', file: " + config.filePath, errCode: 1 } } @@ -708,7 +711,7 @@ var es5_visitors = (function () { function _getParent(node, numberOfParents, config) { if (!node) { throw { - message: "No parent found for node in file: " + config.filePath, + message: "JSParser Error: No parent found for node in file: " + config.filePath, errCode: 1 } } @@ -739,15 +742,15 @@ var es5_visitors = (function () { const extendInfoColumn = extendInfo.column ? extendInfo.column : ""; const extendInfoNewClassName = extendInfo.className ? extendInfo.className : ""; - var lineToWrite = `${extendClass}${ASTERISK_SEPARATOR}` - + `${extendInfoFile}${ASTERISK_SEPARATOR}` - + `${extendInfoLine}${ASTERISK_SEPARATOR}` - + `${extendInfoColumn}${ASTERISK_SEPARATOR}` - + `${extendInfoNewClassName}${ASTERISK_SEPARATOR}` - + `${overriddenMethodNames}${ASTERISK_SEPARATOR}` - + `${classNameFromDecorator}${ASTERISK_SEPARATOR}` - + `${filePath}${ASTERISK_SEPARATOR}` - + `${implementedInterfaces}` + var lineToWrite = `${extendClass}${ASTERISK_SEPARATOR}` + + `${extendInfoFile}${ASTERISK_SEPARATOR}` + + `${extendInfoLine}${ASTERISK_SEPARATOR}` + + `${extendInfoColumn}${ASTERISK_SEPARATOR}` + + `${extendInfoNewClassName}${ASTERISK_SEPARATOR}` + + `${overriddenMethodNames}${ASTERISK_SEPARATOR}` + + `${classNameFromDecorator}${ASTERISK_SEPARATOR}` + + `${filePath}${ASTERISK_SEPARATOR}` + + `${implementedInterfaces}` return lineToWrite; } @@ -772,4 +775,4 @@ var es5_visitors = (function () { } })(); -module.exports = es5_visitors; +module.exports = es5_visitors; \ No newline at end of file diff --git a/test-app/build-tools/static-binding-generator/build.gradle b/test-app/build-tools/static-binding-generator/build.gradle index b8786c877..f21d055e8 100644 --- a/test-app/build-tools/static-binding-generator/build.gradle +++ b/test-app/build-tools/static-binding-generator/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java-library' -sourceCompatibility = JavaVersion.VERSION_1_7 -targetCompatibility = JavaVersion.VERSION_1_7 +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 dependencies { compile 'org.apache.bcel:bcel:6.0' diff --git a/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/GetInterfaceNames.java b/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/GetInterfaceNames.java index fa250e3a7..2394ff8a4 100644 --- a/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/GetInterfaceNames.java +++ b/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/GetInterfaceNames.java @@ -8,6 +8,8 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; @@ -25,18 +27,32 @@ public static void generateInterfaceFile(List rows) String outputFileName = Main.SBG_INTERFACE_NAMES; PrintWriter out = ensureOutputFile(outputFileName); + List interfacesList = Collections.synchronizedList(new ArrayList<>()); - for (DataRow dr : rows) { + final ThrowingConsumer consumer = dr -> { String pathToDependency = dr.getRow(); - if (pathToDependency .endsWith(".jar")) { - generateInterfaceNames(pathToDependency, out); + if (pathToDependency.endsWith(".jar")) { + generateInterfaceNames(pathToDependency, interfacesList); } + }; + + rows.parallelStream().forEach(consumer); + +// for (DataRow dr : rows) { +// String pathToDependency = dr.getRow(); +// if (pathToDependency.endsWith(".jar")) { +// generateInterfaceNames(pathToDependency, interfacesList); +// } +// } + + for(String line: interfacesList) { + out.println(line); } out.close(); } - private static void generateInterfaceNames(String pathToJar, PrintWriter out) throws IOException, ClassNotFoundException { + private static void generateInterfaceNames(String pathToJar, List interfacesList) throws IOException, ClassNotFoundException { if (pathToJar == null) { return; } @@ -62,8 +78,7 @@ private static void generateInterfaceNames(String pathToJar, PrintWriter out) th } if ((c != null) && (c.isInterface() == true)) { String res = c.getName().replace('$', '.'); - - out.println(res); + interfacesList.add(res); } } } diff --git a/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/Main.java b/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/Main.java index 172b73438..6c38f3b2a 100644 --- a/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/Main.java +++ b/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/Main.java @@ -111,6 +111,9 @@ private static void runJsParser() throws IOException { e.printStackTrace(); throw new InterruptedIOException("A problem occured while waiting for the jsparser to finish."); } + if(p.exitValue() != 0) { + System.exit(p.exitValue()); + } } private static Boolean rootTraversed = false; diff --git a/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/ThrowingConsumer.java b/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/ThrowingConsumer.java new file mode 100644 index 000000000..10f7a024c --- /dev/null +++ b/test-app/build-tools/static-binding-generator/src/main/java/org/nativescript/staticbindinggenerator/ThrowingConsumer.java @@ -0,0 +1,18 @@ +package org.nativescript.staticbindinggenerator; + +import java.util.function.Consumer; + +// https://stackoverflow.com/a/27252163/613113 +@FunctionalInterface +public interface ThrowingConsumer extends Consumer { + @Override + default void accept(final T elem) { + try { + acceptThrows(elem); + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + void acceptThrows(T elem) throws Exception; + +} diff --git a/test-app/build.gradle b/test-app/build.gradle index 8b058db62..3ecb8192f 100644 --- a/test-app/build.gradle +++ b/test-app/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:3.2.0' } } diff --git a/test-app/gradle/wrapper/gradle-wrapper.properties b/test-app/gradle/wrapper/gradle-wrapper.properties index 182c48faa..abf11a318 100644 --- a/test-app/gradle/wrapper/gradle-wrapper.properties +++ b/test-app/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri May 11 16:45:47 EEST 2018 +#Thu Sep 27 11:34:03 EEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip diff --git a/test-app/runtime/CMakeLists.txt b/test-app/runtime/CMakeLists.txt index 81ef45d1d..201480572 100644 --- a/test-app/runtime/CMakeLists.txt +++ b/test-app/runtime/CMakeLists.txt @@ -179,12 +179,12 @@ MESSAGE( STATUS "# CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS} ) # linking v8 and inspector libraries to runtime(NativeScript library) target_link_libraries( NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libzip.a ) target_link_libraries( NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libv8_base.a ) +target_link_libraries( NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libv8_snapshot.a ) target_link_libraries( NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libv8_init.a ) target_link_libraries( NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libv8_initializers.a ) target_link_libraries( NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libv8_libplatform.a ) target_link_libraries( NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libv8_libsampler.a ) target_link_libraries( NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libv8_libbase.a ) -target_link_libraries( NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libv8_snapshot.a ) # Command info: https://cmake.org/cmake/help/v3.4/command/find_library.html # Searches for a specified prebuilt library and stores the path as a @@ -195,7 +195,6 @@ target_link_libraries( NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROI find_library( system-log log ) find_library( system-android android ) find_library( system-dl dl ) -find_library( system-atomic atomic ) # TODO: plamen5kov: can't be found in ndk for some reasong ... look at it later (maybe deprecated in newer NDK versions) find_library( system-z z ) # Command info: https://cmake.org/cmake/help/v3.4/command/target_link_libraries.html diff --git a/test-app/runtime/build.gradle b/test-app/runtime/build.gradle index 3b073da53..245c62725 100644 --- a/test-app/runtime/build.gradle +++ b/test-app/runtime/build.gradle @@ -20,7 +20,7 @@ if (useCCache) { println "Use CCache build triggered." } -project.ext._buildToolsVersion = "27.0.3" +project.ext._buildToolsVersion = "28.0.2" android { sourceSets { diff --git a/test-app/runtime/src/main/cpp/ObjectManager.cpp b/test-app/runtime/src/main/cpp/ObjectManager.cpp index 30e6f7244..0c91445a1 100644 --- a/test-app/runtime/src/main/cpp/ObjectManager.cpp +++ b/test-app/runtime/src/main/cpp/ObjectManager.cpp @@ -482,8 +482,8 @@ void ObjectManager::MarkReachableObjects(Isolate* isolate, const Local& } auto o = top.As(); - if(!isInFirstRun) { - uint8_t* addr = NativeScriptExtension::GetAddress(o); + if (!isInFirstRun) { + unsigned long addr = NativeScriptExtension::GetAddress(o); auto itFound = m_visited.find(addr); if (itFound != m_visited.end()) { continue; diff --git a/test-app/runtime/src/main/cpp/ObjectManager.h b/test-app/runtime/src/main/cpp/ObjectManager.h index e30de684f..b3f50c4c7 100644 --- a/test-app/runtime/src/main/cpp/ObjectManager.h +++ b/test-app/runtime/src/main/cpp/ObjectManager.h @@ -201,7 +201,7 @@ class ObjectManager { PersistentObjectIdSet m_released; - std::set m_visited; + std::set m_visited; LRUCache m_cache; diff --git a/test-app/runtime/src/main/cpp/Profiler.cpp b/test-app/runtime/src/main/cpp/Profiler.cpp index 19041181f..b71883eb2 100644 --- a/test-app/runtime/src/main/cpp/Profiler.cpp +++ b/test-app/runtime/src/main/cpp/Profiler.cpp @@ -82,12 +82,12 @@ void Profiler::StopCPUProfilerCallbackImpl(const v8::FunctionCallbackInfo& name) { - auto v8prof = isolate->GetCpuProfiler(); + auto v8prof = CpuProfiler::New(isolate); v8prof->StartProfiling(name, true); } bool Profiler::StopCPUProfiler(Isolate* isolate, const Local& name) { - auto v8prof = isolate->GetCpuProfiler(); + auto v8prof = CpuProfiler::New(isolate); auto cpuProfile = v8prof->StopProfiling(name); auto success = false; diff --git a/test-app/runtime/src/main/cpp/include/V8NativeScriptExtension.h b/test-app/runtime/src/main/cpp/include/V8NativeScriptExtension.h index 60fe9ea7d..55f86a776 100644 --- a/test-app/runtime/src/main/cpp/include/V8NativeScriptExtension.h +++ b/test-app/runtime/src/main/cpp/include/V8NativeScriptExtension.h @@ -1,23 +1,22 @@ #include "v8.h" namespace v8 { - - class NativeScriptExtension { - public: - static uint8_t* GetAddress(const v8::Local& obj); - static v8::Local* GetClosureObjects(v8::Isolate *isolate, const v8::Local& func, int *length); +class NativeScriptExtension { + public: + static unsigned long GetAddress(const v8::Local& obj); - static void ReleaseClosureObjects(v8::Local* closureObjects); - - static void GetAssessorPair(v8::Isolate *isolate, const v8::Local& obj, const v8::Local& propName, v8::Local& getter, v8::Local& setter); + static v8::Local* GetClosureObjects(v8::Isolate* isolate, const v8::Local& func, int* length); - static v8::Local GetPropertyKeys(v8::Isolate *isolate, const v8::Local& context, const v8::Local& object, bool& success); + static void ReleaseClosureObjects(v8::Local* closureObjects); - static void CpuFeaturesProbe(bool cross_compile); - private: - NativeScriptExtension(); + static void GetAssessorPair(v8::Isolate* isolate, const v8::Local& obj, const v8::Local& propName, v8::Local& getter, v8::Local& setter); - // static v8::internal::Handle GetEnumPropertyKeys(const v8::internal::Handle& object, bool cache_result); - }; + static v8::Local GetPropertyKeys(v8::Isolate* isolate, const v8::Local& context, const v8::Local& object, bool& success); + + static void CpuFeaturesProbe(bool cross_compile); + private: + NativeScriptExtension(); +}; } + diff --git a/test-app/runtime/src/main/cpp/include/libplatform/libplatform.h b/test-app/runtime/src/main/cpp/include/libplatform/libplatform.h index dc67fb3d4..22713cbed 100644 --- a/test-app/runtime/src/main/cpp/include/libplatform/libplatform.h +++ b/test-app/runtime/src/main/cpp/include/libplatform/libplatform.h @@ -62,7 +62,7 @@ V8_PLATFORM_EXPORT bool PumpMessageLoop( v8::Platform* platform, v8::Isolate* isolate, MessageLoopBehavior behavior = MessageLoopBehavior::kDoNotWait); -V8_PLATFORM_EXPORT V8_DEPRECATE_SOON( +V8_PLATFORM_EXPORT V8_DEPRECATED( "This function has become obsolete and is essentially a nop", void EnsureEventLoopInitialized(v8::Platform* platform, v8::Isolate* isolate)); diff --git a/test-app/runtime/src/main/cpp/include/libplatform/v8-tracing.h b/test-app/runtime/src/main/cpp/include/libplatform/v8-tracing.h index 9dcf3d7bc..02f15955b 100644 --- a/test-app/runtime/src/main/cpp/include/libplatform/v8-tracing.h +++ b/test-app/runtime/src/main/cpp/include/libplatform/v8-tracing.h @@ -25,188 +25,242 @@ namespace tracing { const int kTraceMaxNumArgs = 2; class V8_PLATFORM_EXPORT TraceObject { - public: - union ArgValue { - bool as_bool; - uint64_t as_uint; - int64_t as_int; - double as_double; - const void* as_pointer; - const char* as_string; - }; - - TraceObject() {} - ~TraceObject(); - void Initialize( - char phase, const uint8_t* category_enabled_flag, const char* name, - const char* scope, uint64_t id, uint64_t bind_id, int num_args, - const char** arg_names, const uint8_t* arg_types, - const uint64_t* arg_values, - std::unique_ptr* arg_convertables, - unsigned int flags, int64_t timestamp, int64_t cpu_timestamp); - void UpdateDuration(int64_t timestamp, int64_t cpu_timestamp); - void InitializeForTesting( - char phase, const uint8_t* category_enabled_flag, const char* name, - const char* scope, uint64_t id, uint64_t bind_id, int num_args, - const char** arg_names, const uint8_t* arg_types, - const uint64_t* arg_values, - std::unique_ptr* arg_convertables, - unsigned int flags, int pid, int tid, int64_t ts, int64_t tts, - uint64_t duration, uint64_t cpu_duration); - - int pid() const { return pid_; } - int tid() const { return tid_; } - char phase() const { return phase_; } - const uint8_t* category_enabled_flag() const { - return category_enabled_flag_; - } - const char* name() const { return name_; } - const char* scope() const { return scope_; } - uint64_t id() const { return id_; } - uint64_t bind_id() const { return bind_id_; } - int num_args() const { return num_args_; } - const char** arg_names() { return arg_names_; } - uint8_t* arg_types() { return arg_types_; } - ArgValue* arg_values() { return arg_values_; } - std::unique_ptr* arg_convertables() { - return arg_convertables_; - } - unsigned int flags() const { return flags_; } - int64_t ts() { return ts_; } - int64_t tts() { return tts_; } - uint64_t duration() { return duration_; } - uint64_t cpu_duration() { return cpu_duration_; } - - private: - int pid_; - int tid_; - char phase_; - const char* name_; - const char* scope_; - const uint8_t* category_enabled_flag_; - uint64_t id_; - uint64_t bind_id_; - int num_args_ = 0; - const char* arg_names_[kTraceMaxNumArgs]; - uint8_t arg_types_[kTraceMaxNumArgs]; - ArgValue arg_values_[kTraceMaxNumArgs]; - std::unique_ptr - arg_convertables_[kTraceMaxNumArgs]; - char* parameter_copy_storage_ = nullptr; - unsigned int flags_; - int64_t ts_; - int64_t tts_; - uint64_t duration_; - uint64_t cpu_duration_; - - // Disallow copy and assign - TraceObject(const TraceObject&) = delete; - void operator=(const TraceObject&) = delete; + public: + union ArgValue { + bool as_bool; + uint64_t as_uint; + int64_t as_int; + double as_double; + const void* as_pointer; + const char* as_string; + }; + + TraceObject() {} + ~TraceObject(); + void Initialize( + char phase, const uint8_t* category_enabled_flag, const char* name, + const char* scope, uint64_t id, uint64_t bind_id, int num_args, + const char** arg_names, const uint8_t* arg_types, + const uint64_t* arg_values, + std::unique_ptr* arg_convertables, + unsigned int flags, int64_t timestamp, int64_t cpu_timestamp); + void UpdateDuration(int64_t timestamp, int64_t cpu_timestamp); + void InitializeForTesting( + char phase, const uint8_t* category_enabled_flag, const char* name, + const char* scope, uint64_t id, uint64_t bind_id, int num_args, + const char** arg_names, const uint8_t* arg_types, + const uint64_t* arg_values, + std::unique_ptr* arg_convertables, + unsigned int flags, int pid, int tid, int64_t ts, int64_t tts, + uint64_t duration, uint64_t cpu_duration); + + int pid() const { + return pid_; + } + int tid() const { + return tid_; + } + char phase() const { + return phase_; + } + const uint8_t* category_enabled_flag() const { + return category_enabled_flag_; + } + const char* name() const { + return name_; + } + const char* scope() const { + return scope_; + } + uint64_t id() const { + return id_; + } + uint64_t bind_id() const { + return bind_id_; + } + int num_args() const { + return num_args_; + } + const char** arg_names() { + return arg_names_; + } + uint8_t* arg_types() { + return arg_types_; + } + ArgValue* arg_values() { + return arg_values_; + } + std::unique_ptr* arg_convertables() { + return arg_convertables_; + } + unsigned int flags() const { + return flags_; + } + int64_t ts() { + return ts_; + } + int64_t tts() { + return tts_; + } + uint64_t duration() { + return duration_; + } + uint64_t cpu_duration() { + return cpu_duration_; + } + + private: + int pid_; + int tid_; + char phase_; + const char* name_; + const char* scope_; + const uint8_t* category_enabled_flag_; + uint64_t id_; + uint64_t bind_id_; + int num_args_ = 0; + const char* arg_names_[kTraceMaxNumArgs]; + uint8_t arg_types_[kTraceMaxNumArgs]; + ArgValue arg_values_[kTraceMaxNumArgs]; + std::unique_ptr + arg_convertables_[kTraceMaxNumArgs]; + char* parameter_copy_storage_ = nullptr; + unsigned int flags_; + int64_t ts_; + int64_t tts_; + uint64_t duration_; + uint64_t cpu_duration_; + + // Disallow copy and assign + TraceObject(const TraceObject&) = delete; + void operator=(const TraceObject&) = delete; }; class V8_PLATFORM_EXPORT TraceWriter { - public: - TraceWriter() {} - virtual ~TraceWriter() {} - virtual void AppendTraceEvent(TraceObject* trace_event) = 0; - virtual void Flush() = 0; - - static TraceWriter* CreateJSONTraceWriter(std::ostream& stream); - - private: - // Disallow copy and assign - TraceWriter(const TraceWriter&) = delete; - void operator=(const TraceWriter&) = delete; + public: + TraceWriter() {} + virtual ~TraceWriter() {} + virtual void AppendTraceEvent(TraceObject* trace_event) = 0; + 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 + TraceWriter(const TraceWriter&) = delete; + void operator=(const TraceWriter&) = delete; }; class V8_PLATFORM_EXPORT TraceBufferChunk { - public: - explicit TraceBufferChunk(uint32_t seq); - - void Reset(uint32_t new_seq); - bool IsFull() const { return next_free_ == kChunkSize; } - TraceObject* AddTraceEvent(size_t* event_index); - TraceObject* GetEventAt(size_t index) { return &chunk_[index]; } - - uint32_t seq() const { return seq_; } - size_t size() const { return next_free_; } - - static const size_t kChunkSize = 64; - - private: - size_t next_free_ = 0; - TraceObject chunk_[kChunkSize]; - uint32_t seq_; - - // Disallow copy and assign - TraceBufferChunk(const TraceBufferChunk&) = delete; - void operator=(const TraceBufferChunk&) = delete; + public: + explicit TraceBufferChunk(uint32_t seq); + + void Reset(uint32_t new_seq); + bool IsFull() const { + return next_free_ == kChunkSize; + } + TraceObject* AddTraceEvent(size_t* event_index); + TraceObject* GetEventAt(size_t index) { + return &chunk_[index]; + } + + uint32_t seq() const { + return seq_; + } + size_t size() const { + return next_free_; + } + + static const size_t kChunkSize = 64; + + private: + size_t next_free_ = 0; + TraceObject chunk_[kChunkSize]; + uint32_t seq_; + + // Disallow copy and assign + TraceBufferChunk(const TraceBufferChunk&) = delete; + void operator=(const TraceBufferChunk&) = delete; }; class V8_PLATFORM_EXPORT TraceBuffer { - public: - TraceBuffer() {} - virtual ~TraceBuffer() {} + public: + TraceBuffer() {} + virtual ~TraceBuffer() {} - virtual TraceObject* AddTraceEvent(uint64_t* handle) = 0; - virtual TraceObject* GetEventByHandle(uint64_t handle) = 0; - virtual bool Flush() = 0; + virtual TraceObject* AddTraceEvent(uint64_t* handle) = 0; + virtual TraceObject* GetEventByHandle(uint64_t handle) = 0; + virtual bool Flush() = 0; - static const size_t kRingBufferChunks = 1024; + static const size_t kRingBufferChunks = 1024; - static TraceBuffer* CreateTraceBufferRingBuffer(size_t max_chunks, - TraceWriter* trace_writer); + static TraceBuffer* CreateTraceBufferRingBuffer(size_t max_chunks, + TraceWriter* trace_writer); - private: - // Disallow copy and assign - TraceBuffer(const TraceBuffer&) = delete; - void operator=(const TraceBuffer&) = delete; + private: + // Disallow copy and assign + TraceBuffer(const TraceBuffer&) = delete; + void operator=(const TraceBuffer&) = delete; }; // Options determines how the trace buffer stores data. enum TraceRecordMode { - // Record until the trace buffer is full. - RECORD_UNTIL_FULL, + // Record until the trace buffer is full. + RECORD_UNTIL_FULL, - // Record until the user ends the trace. The trace buffer is a fixed size - // and we use it as a ring buffer during recording. - RECORD_CONTINUOUSLY, + // Record until the user ends the trace. The trace buffer is a fixed size + // and we use it as a ring buffer during recording. + RECORD_CONTINUOUSLY, - // Record until the trace buffer is full, but with a huge buffer size. - RECORD_AS_MUCH_AS_POSSIBLE, + // Record until the trace buffer is full, but with a huge buffer size. + RECORD_AS_MUCH_AS_POSSIBLE, - // Echo to console. Events are discarded. - ECHO_TO_CONSOLE, + // Echo to console. Events are discarded. + ECHO_TO_CONSOLE, }; class V8_PLATFORM_EXPORT TraceConfig { - public: - typedef std::vector StringList; - - static TraceConfig* CreateDefaultTraceConfig(); - - TraceConfig() : enable_systrace_(false), enable_argument_filter_(false) {} - TraceRecordMode GetTraceRecordMode() const { return record_mode_; } - bool IsSystraceEnabled() const { return enable_systrace_; } - bool IsArgumentFilterEnabled() const { return enable_argument_filter_; } - - void SetTraceRecordMode(TraceRecordMode mode) { record_mode_ = mode; } - void EnableSystrace() { enable_systrace_ = true; } - void EnableArgumentFilter() { enable_argument_filter_ = true; } - - void AddIncludedCategory(const char* included_category); - - bool IsCategoryGroupEnabled(const char* category_group) const; - - private: - TraceRecordMode record_mode_; - bool enable_systrace_ : 1; - bool enable_argument_filter_ : 1; - StringList included_categories_; - - // Disallow copy and assign - TraceConfig(const TraceConfig&) = delete; - void operator=(const TraceConfig&) = delete; + public: + typedef std::vector StringList; + + static TraceConfig* CreateDefaultTraceConfig(); + + TraceConfig() : enable_systrace_(false), enable_argument_filter_(false) {} + TraceRecordMode GetTraceRecordMode() const { + return record_mode_; + } + bool IsSystraceEnabled() const { + return enable_systrace_; + } + bool IsArgumentFilterEnabled() const { + return enable_argument_filter_; + } + + void SetTraceRecordMode(TraceRecordMode mode) { + record_mode_ = mode; + } + void EnableSystrace() { + enable_systrace_ = true; + } + void EnableArgumentFilter() { + enable_argument_filter_ = true; + } + + void AddIncludedCategory(const char* included_category); + + bool IsCategoryGroupEnabled(const char* category_group) const; + + private: + TraceRecordMode record_mode_; + bool enable_systrace_ : 1; + bool enable_argument_filter_ : 1; + StringList included_categories_; + + // Disallow copy and assign + TraceConfig(const TraceConfig&) = delete; + void operator=(const TraceConfig&) = delete; }; #if defined(_MSC_VER) @@ -218,72 +272,72 @@ class V8_PLATFORM_EXPORT TraceConfig { class V8_PLATFORM_EXPORT TracingController : public V8_PLATFORM_NON_EXPORTED_BASE(v8::TracingController) { - public: - enum Mode { DISABLED = 0, RECORDING_MODE }; - - // The pointer returned from GetCategoryGroupEnabledInternal() points to a - // value with zero or more of the following bits. Used in this class only. - // The TRACE_EVENT macros should only use the value as a bool. - // These values must be in sync with macro values in TraceEvent.h in Blink. - enum CategoryGroupEnabledFlags { - // Category group enabled for the recording mode. - ENABLED_FOR_RECORDING = 1 << 0, - // Category group enabled by SetEventCallbackEnabled(). - ENABLED_FOR_EVENT_CALLBACK = 1 << 2, - // Category group enabled to export events to ETW. - ENABLED_FOR_ETW_EXPORT = 1 << 3 - }; - - TracingController(); - ~TracingController() override; - void Initialize(TraceBuffer* trace_buffer); - - // v8::TracingController implementation. - const uint8_t* GetCategoryGroupEnabled(const char* category_group) override; - uint64_t AddTraceEvent( - char phase, const uint8_t* category_enabled_flag, const char* name, - const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, - const char** arg_names, const uint8_t* arg_types, - const uint64_t* arg_values, - std::unique_ptr* arg_convertables, - unsigned int flags) override; - uint64_t AddTraceEventWithTimestamp( - char phase, const uint8_t* category_enabled_flag, const char* name, - const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, - const char** arg_names, const uint8_t* arg_types, - const uint64_t* arg_values, - std::unique_ptr* arg_convertables, - unsigned int flags, int64_t timestamp) override; - void UpdateTraceEventDuration(const uint8_t* category_enabled_flag, - const char* name, uint64_t handle) override; - void AddTraceStateObserver( - v8::TracingController::TraceStateObserver* observer) override; - void RemoveTraceStateObserver( - v8::TracingController::TraceStateObserver* observer) override; - - void StartTracing(TraceConfig* trace_config); - void StopTracing(); - - static const char* GetCategoryGroupName(const uint8_t* category_enabled_flag); - - protected: - virtual int64_t CurrentTimestampMicroseconds(); - virtual int64_t CurrentCpuTimestampMicroseconds(); - - private: - const uint8_t* GetCategoryGroupEnabledInternal(const char* category_group); - void UpdateCategoryGroupEnabledFlag(size_t category_index); - void UpdateCategoryGroupEnabledFlags(); - - std::unique_ptr trace_buffer_; - std::unique_ptr trace_config_; - std::unique_ptr mutex_; - std::unordered_set observers_; - Mode mode_ = DISABLED; - - // Disallow copy and assign - TracingController(const TracingController&) = delete; - void operator=(const TracingController&) = delete; + public: + enum Mode { DISABLED = 0, RECORDING_MODE }; + + // The pointer returned from GetCategoryGroupEnabledInternal() points to a + // value with zero or more of the following bits. Used in this class only. + // The TRACE_EVENT macros should only use the value as a bool. + // These values must be in sync with macro values in TraceEvent.h in Blink. + enum CategoryGroupEnabledFlags { + // Category group enabled for the recording mode. + ENABLED_FOR_RECORDING = 1 << 0, + // Category group enabled by SetEventCallbackEnabled(). + ENABLED_FOR_EVENT_CALLBACK = 1 << 2, + // Category group enabled to export events to ETW. + ENABLED_FOR_ETW_EXPORT = 1 << 3 + }; + + TracingController(); + ~TracingController() override; + void Initialize(TraceBuffer* trace_buffer); + + // v8::TracingController implementation. + const uint8_t* GetCategoryGroupEnabled(const char* category_group) override; + uint64_t AddTraceEvent( + char phase, const uint8_t* category_enabled_flag, const char* name, + const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, + const char** arg_names, const uint8_t* arg_types, + const uint64_t* arg_values, + std::unique_ptr* arg_convertables, + unsigned int flags) override; + uint64_t AddTraceEventWithTimestamp( + char phase, const uint8_t* category_enabled_flag, const char* name, + const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, + const char** arg_names, const uint8_t* arg_types, + const uint64_t* arg_values, + std::unique_ptr* arg_convertables, + unsigned int flags, int64_t timestamp) override; + void UpdateTraceEventDuration(const uint8_t* category_enabled_flag, + const char* name, uint64_t handle) override; + void AddTraceStateObserver( + v8::TracingController::TraceStateObserver* observer) override; + void RemoveTraceStateObserver( + v8::TracingController::TraceStateObserver* observer) override; + + void StartTracing(TraceConfig* trace_config); + void StopTracing(); + + static const char* GetCategoryGroupName(const uint8_t* category_enabled_flag); + + protected: + virtual int64_t CurrentTimestampMicroseconds(); + virtual int64_t CurrentCpuTimestampMicroseconds(); + + private: + const uint8_t* GetCategoryGroupEnabledInternal(const char* category_group); + void UpdateCategoryGroupEnabledFlag(size_t category_index); + void UpdateCategoryGroupEnabledFlags(); + + std::unique_ptr trace_buffer_; + std::unique_ptr trace_config_; + std::unique_ptr mutex_; + std::unordered_set observers_; + Mode mode_ = DISABLED; + + // Disallow copy and assign + TracingController(const TracingController&) = delete; + void operator=(const TracingController&) = delete; }; #undef V8_PLATFORM_NON_EXPORTED_BASE diff --git a/test-app/runtime/src/main/cpp/include/v8-inspector.h b/test-app/runtime/src/main/cpp/include/v8-inspector.h index 6de8234fb..f28470b56 100644 --- a/test-app/runtime/src/main/cpp/include/v8-inspector.h +++ b/test-app/runtime/src/main/cpp/include/v8-inspector.h @@ -34,254 +34,269 @@ class Domain; } // namespace protocol class V8_EXPORT StringView { - public: - StringView() : m_is8Bit(true), m_length(0), m_characters8(nullptr) {} - - StringView(const uint8_t* characters, size_t length) - : m_is8Bit(true), m_length(length), m_characters8(characters) {} - - StringView(const uint16_t* characters, size_t length) - : m_is8Bit(false), m_length(length), m_characters16(characters) {} - - bool is8Bit() const { return m_is8Bit; } - size_t length() const { return m_length; } - - // TODO(dgozman): add DCHECK(m_is8Bit) to accessors once platform can be used - // here. - const uint8_t* characters8() const { return m_characters8; } - const uint16_t* characters16() const { return m_characters16; } - - private: - bool m_is8Bit; - size_t m_length; - union { - const uint8_t* m_characters8; - const uint16_t* m_characters16; - }; + public: + StringView() : m_is8Bit(true), m_length(0), m_characters8(nullptr) {} + + StringView(const uint8_t* characters, size_t length) + : m_is8Bit(true), m_length(length), m_characters8(characters) {} + + StringView(const uint16_t* characters, size_t length) + : m_is8Bit(false), m_length(length), m_characters16(characters) {} + + bool is8Bit() const { + return m_is8Bit; + } + size_t length() const { + return m_length; + } + + // TODO(dgozman): add DCHECK(m_is8Bit) to accessors once platform can be used + // here. + const uint8_t* characters8() const { + return m_characters8; + } + const uint16_t* characters16() const { + return m_characters16; + } + + private: + bool m_is8Bit; + size_t m_length; + union { + const uint8_t* m_characters8; + const uint16_t* m_characters16; + }; }; class V8_EXPORT StringBuffer { - public: - virtual ~StringBuffer() {} - virtual const StringView& string() = 0; - // This method copies contents. - static std::unique_ptr create(const StringView&); + public: + virtual ~StringBuffer() {} + virtual const StringView& string() = 0; + // This method copies contents. + static std::unique_ptr create(const StringView&); }; class V8_EXPORT V8ContextInfo { - public: - V8ContextInfo(v8::Local context, int contextGroupId, - const StringView& humanReadableName) - : context(context), - contextGroupId(contextGroupId), - humanReadableName(humanReadableName), - hasMemoryOnConsole(false) {} - - v8::Local context; - // Each v8::Context is a part of a group. The group id must be non-zero. - int contextGroupId; - StringView humanReadableName; - StringView origin; - StringView auxData; - bool hasMemoryOnConsole; - - static int executionContextId(v8::Local context); - - private: - // Disallow copying and allocating this one. - enum NotNullTagEnum { NotNullLiteral }; - void* operator new(size_t) = delete; - void* operator new(size_t, NotNullTagEnum, void*) = delete; - void* operator new(size_t, void*) = delete; - V8ContextInfo(const V8ContextInfo&) = delete; - V8ContextInfo& operator=(const V8ContextInfo&) = delete; + public: + V8ContextInfo(v8::Local context, int contextGroupId, + const StringView& humanReadableName) + : context(context), + contextGroupId(contextGroupId), + humanReadableName(humanReadableName), + hasMemoryOnConsole(false) {} + + v8::Local context; + // Each v8::Context is a part of a group. The group id must be non-zero. + int contextGroupId; + StringView humanReadableName; + StringView origin; + StringView auxData; + bool hasMemoryOnConsole; + + static int executionContextId(v8::Local context); + + private: + // Disallow copying and allocating this one. + enum NotNullTagEnum { NotNullLiteral }; + void* operator new(size_t) = delete; + void* operator new(size_t, NotNullTagEnum, void*) = delete; + void* operator new(size_t, void*) = delete; + V8ContextInfo(const V8ContextInfo&) = delete; + V8ContextInfo& operator=(const V8ContextInfo&) = delete; }; class V8_EXPORT V8StackTrace { - public: - virtual bool isEmpty() const = 0; - virtual StringView topSourceURL() const = 0; - virtual int topLineNumber() const = 0; - virtual int topColumnNumber() const = 0; - virtual StringView topScriptId() const = 0; - virtual StringView topFunctionName() const = 0; - - virtual ~V8StackTrace() {} - virtual std::unique_ptr - buildInspectorObject() const = 0; - virtual std::unique_ptr toString() const = 0; - - // Safe to pass between threads, drops async chain. - virtual std::unique_ptr clone() = 0; + public: + virtual StringView firstNonEmptySourceURL() const = 0; + virtual bool isEmpty() const = 0; + virtual StringView topSourceURL() const = 0; + virtual int topLineNumber() const = 0; + virtual int topColumnNumber() const = 0; + virtual StringView topScriptId() const = 0; + virtual StringView topFunctionName() const = 0; + + virtual ~V8StackTrace() {} + virtual std::unique_ptr + buildInspectorObject() const = 0; + virtual std::unique_ptr toString() const = 0; + + // Safe to pass between threads, drops async chain. + virtual std::unique_ptr clone() = 0; }; class V8_EXPORT V8InspectorSession { - public: - virtual ~V8InspectorSession() {} - - // Cross-context inspectable values (DOM nodes in different worlds, etc.). - class V8_EXPORT Inspectable { - public: - virtual v8::Local get(v8::Local) = 0; - virtual ~Inspectable() {} - }; - virtual void addInspectedObject(std::unique_ptr) = 0; - - // Dispatching protocol messages. - static bool canDispatchMethod(const StringView& method); - virtual void dispatchProtocolMessage(const StringView& message) = 0; - virtual std::unique_ptr stateJSON() = 0; - virtual std::vector> - supportedDomains() = 0; - - // Debugger actions. - virtual void schedulePauseOnNextStatement(const StringView& breakReason, - const StringView& breakDetails) = 0; - virtual void cancelPauseOnNextStatement() = 0; - virtual void breakProgram(const StringView& breakReason, - const StringView& breakDetails) = 0; - virtual void setSkipAllPauses(bool) = 0; - virtual void resume() = 0; - virtual void stepOver() = 0; - virtual std::vector> - searchInTextByLines(const StringView& text, const StringView& query, - bool caseSensitive, bool isRegex) = 0; - - // Remote objects. - virtual std::unique_ptr wrapObject( - v8::Local, v8::Local, const StringView& groupName, - bool generatePreview) = 0; - - virtual bool unwrapObject(std::unique_ptr* error, - const StringView& objectId, v8::Local*, - v8::Local*, - std::unique_ptr* objectGroup) = 0; - virtual void releaseObjectGroup(const StringView&) = 0; + public: + virtual ~V8InspectorSession() {} + + // Cross-context inspectable values (DOM nodes in different worlds, etc.). + class V8_EXPORT Inspectable { + public: + virtual v8::Local get(v8::Local) = 0; + virtual ~Inspectable() {} + }; + virtual void addInspectedObject(std::unique_ptr) = 0; + + // Dispatching protocol messages. + static bool canDispatchMethod(const StringView& method); + virtual void dispatchProtocolMessage(const StringView& message) = 0; + virtual std::unique_ptr stateJSON() = 0; + virtual std::vector> + supportedDomains() = 0; + + // Debugger actions. + virtual void schedulePauseOnNextStatement(const StringView& breakReason, + const StringView& breakDetails) = 0; + virtual void cancelPauseOnNextStatement() = 0; + virtual void breakProgram(const StringView& breakReason, + const StringView& breakDetails) = 0; + virtual void setSkipAllPauses(bool) = 0; + virtual void resume() = 0; + virtual void stepOver() = 0; + virtual std::vector> + searchInTextByLines(const StringView& text, const StringView& query, + bool caseSensitive, bool isRegex) = 0; + + // Remote objects. + virtual std::unique_ptr wrapObject( + v8::Local, v8::Local, const StringView& groupName, + bool generatePreview) = 0; + + virtual bool unwrapObject(std::unique_ptr* error, + const StringView& objectId, v8::Local*, + v8::Local*, + std::unique_ptr* objectGroup) = 0; + virtual void releaseObjectGroup(const StringView&) = 0; }; class V8_EXPORT V8InspectorClient { - public: - virtual ~V8InspectorClient() {} - - virtual void runMessageLoopOnPause(int contextGroupId) {} - virtual void quitMessageLoopOnPause() {} - virtual void runIfWaitingForDebugger(int contextGroupId) {} - - virtual void muteMetrics(int contextGroupId) {} - virtual void unmuteMetrics(int contextGroupId) {} - - virtual void beginUserGesture() {} - virtual void endUserGesture() {} - - virtual std::unique_ptr valueSubtype(v8::Local) { - return nullptr; - } - virtual bool formatAccessorsAsProperties(v8::Local) { - return false; - } - virtual bool isInspectableHeapObject(v8::Local) { return true; } - - virtual v8::Local ensureDefaultContextInGroup( - int contextGroupId) { - return v8::Local(); - } - virtual void beginEnsureAllContextsInGroup(int contextGroupId) {} - virtual void endEnsureAllContextsInGroup(int contextGroupId) {} - - virtual void installAdditionalCommandLineAPI(v8::Local, - v8::Local) {} - virtual void consoleAPIMessage(int contextGroupId, - v8::Isolate::MessageErrorLevel level, - const StringView& message, - const StringView& url, unsigned lineNumber, - unsigned columnNumber, V8StackTrace*) {} - virtual v8::MaybeLocal memoryInfo(v8::Isolate*, - v8::Local) { - return v8::MaybeLocal(); - } - - virtual void consoleTime(const StringView& title) {} - virtual void consoleTimeEnd(const StringView& title) {} - virtual void consoleTimeStamp(const StringView& title) {} - virtual void consoleClear(int contextGroupId) {} - virtual double currentTimeMS() { return 0; } - typedef void (*TimerCallback)(void*); - virtual void startRepeatingTimer(double, TimerCallback, void* data) {} - virtual void cancelTimer(void* data) {} - - // TODO(dgozman): this was added to support service worker shadow page. We - // should not connect at all. - virtual bool canExecuteScripts(int contextGroupId) { return true; } - - virtual void maxAsyncCallStackDepthChanged(int depth) {} + public: + virtual ~V8InspectorClient() {} + + virtual void runMessageLoopOnPause(int contextGroupId) {} + virtual void quitMessageLoopOnPause() {} + virtual void runIfWaitingForDebugger(int contextGroupId) {} + + virtual void muteMetrics(int contextGroupId) {} + virtual void unmuteMetrics(int contextGroupId) {} + + virtual void beginUserGesture() {} + virtual void endUserGesture() {} + + virtual std::unique_ptr valueSubtype(v8::Local) { + return nullptr; + } + virtual bool formatAccessorsAsProperties(v8::Local) { + return false; + } + virtual bool isInspectableHeapObject(v8::Local) { + return true; + } + + virtual v8::Local ensureDefaultContextInGroup( + int contextGroupId) { + return v8::Local(); + } + virtual void beginEnsureAllContextsInGroup(int contextGroupId) {} + virtual void endEnsureAllContextsInGroup(int contextGroupId) {} + + virtual void installAdditionalCommandLineAPI(v8::Local, + v8::Local) {} + virtual void consoleAPIMessage(int contextGroupId, + v8::Isolate::MessageErrorLevel level, + const StringView& message, + const StringView& url, unsigned lineNumber, + unsigned columnNumber, V8StackTrace*) {} + virtual v8::MaybeLocal memoryInfo(v8::Isolate*, + v8::Local) { + return v8::MaybeLocal(); + } + + virtual void consoleTime(const StringView& title) {} + virtual void consoleTimeEnd(const StringView& title) {} + virtual void consoleTimeStamp(const StringView& title) {} + virtual void consoleClear(int contextGroupId) {} + virtual double currentTimeMS() { + return 0; + } + typedef void (*TimerCallback)(void*); + virtual void startRepeatingTimer(double, TimerCallback, void* data) {} + virtual void cancelTimer(void* data) {} + + // TODO(dgozman): this was added to support service worker shadow page. We + // should not connect at all. + virtual bool canExecuteScripts(int contextGroupId) { + return true; + } + + virtual void maxAsyncCallStackDepthChanged(int depth) {} }; // These stack trace ids are intended to be passed between debuggers and be // resolved later. This allows to track cross-debugger calls and step between // them if a single client connects to multiple debuggers. struct V8_EXPORT V8StackTraceId { - uintptr_t id; - std::pair debugger_id; + uintptr_t id; + std::pair debugger_id; - V8StackTraceId(); - V8StackTraceId(uintptr_t id, const std::pair debugger_id); - ~V8StackTraceId() = default; + V8StackTraceId(); + V8StackTraceId(uintptr_t id, const std::pair debugger_id); + ~V8StackTraceId() = default; - bool IsInvalid() const; + bool IsInvalid() const; }; class V8_EXPORT V8Inspector { - public: - static std::unique_ptr create(v8::Isolate*, V8InspectorClient*); - virtual ~V8Inspector() {} - - // Contexts instrumentation. - virtual void contextCreated(const V8ContextInfo&) = 0; - virtual void contextDestroyed(v8::Local) = 0; - virtual void resetContextGroup(int contextGroupId) = 0; - - // Various instrumentation. - virtual void idleStarted() = 0; - virtual void idleFinished() = 0; - - // Async stack traces instrumentation. - virtual void asyncTaskScheduled(const StringView& taskName, void* task, - bool recurring) = 0; - virtual void asyncTaskCanceled(void* task) = 0; - virtual void asyncTaskStarted(void* task) = 0; - virtual void asyncTaskFinished(void* task) = 0; - virtual void allAsyncTasksCanceled() = 0; - - virtual V8StackTraceId storeCurrentStackTrace( - const StringView& description) = 0; - virtual void externalAsyncTaskStarted(const V8StackTraceId& parent) = 0; - virtual void externalAsyncTaskFinished(const V8StackTraceId& parent) = 0; - - // Exceptions instrumentation. - virtual unsigned exceptionThrown( - v8::Local, const StringView& message, - v8::Local exception, const StringView& detailedMessage, - const StringView& url, unsigned lineNumber, unsigned columnNumber, - std::unique_ptr, int scriptId) = 0; - virtual void exceptionRevoked(v8::Local, unsigned exceptionId, - const StringView& message) = 0; - - // Connection. - class V8_EXPORT Channel { - public: - virtual ~Channel() {} - virtual void sendResponse(int callId, - std::unique_ptr message) = 0; - virtual void sendNotification(std::unique_ptr message) = 0; - virtual void flushProtocolNotifications() = 0; - }; - virtual std::unique_ptr connect( - int contextGroupId, Channel*, const StringView& state) = 0; - - // API methods. - virtual std::unique_ptr createStackTrace( - v8::Local) = 0; - virtual std::unique_ptr captureStackTrace(bool fullStack) = 0; + public: + static std::unique_ptr create(v8::Isolate*, V8InspectorClient*); + virtual ~V8Inspector() {} + + // Contexts instrumentation. + virtual void contextCreated(const V8ContextInfo&) = 0; + virtual void contextDestroyed(v8::Local) = 0; + virtual void resetContextGroup(int contextGroupId) = 0; + + // Various instrumentation. + virtual void idleStarted() = 0; + virtual void idleFinished() = 0; + + // Async stack traces instrumentation. + virtual void asyncTaskScheduled(const StringView& taskName, void* task, + bool recurring) = 0; + virtual void asyncTaskCanceled(void* task) = 0; + virtual void asyncTaskStarted(void* task) = 0; + virtual void asyncTaskFinished(void* task) = 0; + virtual void allAsyncTasksCanceled() = 0; + + virtual V8StackTraceId storeCurrentStackTrace( + const StringView& description) = 0; + virtual void externalAsyncTaskStarted(const V8StackTraceId& parent) = 0; + virtual void externalAsyncTaskFinished(const V8StackTraceId& parent) = 0; + + // Exceptions instrumentation. + virtual unsigned exceptionThrown( + v8::Local, const StringView& message, + v8::Local exception, const StringView& detailedMessage, + const StringView& url, unsigned lineNumber, unsigned columnNumber, + std::unique_ptr, int scriptId) = 0; + virtual void exceptionRevoked(v8::Local, unsigned exceptionId, + const StringView& message) = 0; + + // Connection. + class V8_EXPORT Channel { + public: + virtual ~Channel() {} + virtual void sendResponse(int callId, + std::unique_ptr message) = 0; + virtual void sendNotification(std::unique_ptr message) = 0; + virtual void flushProtocolNotifications() = 0; + }; + virtual std::unique_ptr connect( + int contextGroupId, Channel*, const StringView& state) = 0; + + // API methods. + virtual std::unique_ptr createStackTrace( + v8::Local) = 0; + virtual std::unique_ptr captureStackTrace(bool fullStack) = 0; }; } // namespace v8_inspector diff --git a/test-app/runtime/src/main/cpp/include/v8-platform.h b/test-app/runtime/src/main/cpp/include/v8-platform.h index b6c08c103..590ae2eaa 100644 --- a/test-app/runtime/src/main/cpp/include/v8-platform.h +++ b/test-app/runtime/src/main/cpp/include/v8-platform.h @@ -207,6 +207,7 @@ class PageAllocator { */ enum Permission { kNoAccess, + kRead, kReadWrite, // TODO(hpayer): Remove this flag. Memory should never be rwx. kReadWriteExecute, @@ -245,16 +246,6 @@ class PageAllocator { */ class Platform { public: - /** - * This enum is used to indicate whether a task is potentially long running, - * or causes a long wait. The embedder might want to use this hint to decide - * whether to execute the task on a dedicated thread. - */ - enum ExpectedRuntime { - kShortRunningTask, - kLongRunningTask - }; - virtual ~Platform() = default; /** @@ -291,101 +282,25 @@ class Platform { } /** - * Gets the number of worker threads used by GetWorkerThreadsTaskRunner() and - * CallOnWorkerThread(). This can be used to estimate the number of tasks a - * work package should be split into. A return value of 0 means that there are - * no worker threads available. Note that a value of 0 won't prohibit V8 from - * posting tasks using |CallOnWorkerThread|. - */ - virtual int NumberOfWorkerThreads() { - return static_cast(NumberOfAvailableBackgroundThreads()); - } - - /** - * Deprecated. Use NumberOfWorkerThreads() instead. - * TODO(gab): Remove this when all embedders override - * NumberOfWorkerThreads() instead. + * Gets the number of worker threads used by + * Call(BlockingTask)OnWorkerThread(). This can be used to estimate the number + * of tasks a work package should be split into. A return value of 0 means + * that there are no worker threads available. Note that a value of 0 won't + * prohibit V8 from posting tasks using |CallOnWorkerThread|. */ - V8_DEPRECATE_SOON( - "NumberOfAvailableBackgroundThreads() is deprecated, use " - "NumberOfAvailableBackgroundThreads() instead.", - virtual size_t NumberOfAvailableBackgroundThreads()) { - return 0; - } + virtual int NumberOfWorkerThreads() = 0; /** * Returns a TaskRunner which can be used to post a task on the foreground. * This function should only be called from a foreground thread. */ virtual std::shared_ptr GetForegroundTaskRunner( - Isolate* isolate) { - // TODO(ahaas): Make this function abstract after it got implemented on all - // platforms. - return {}; - } - - /** - * Returns a TaskRunner which can be used to post a task on a background. - * This function should only be called from a foreground thread. - */ - V8_DEPRECATE_SOON( - "GetBackgroundTaskRunner() is deprecated, use " - "GetWorkerThreadsTaskRunner() " - "instead.", - virtual std::shared_ptr GetBackgroundTaskRunner( - Isolate* isolate)) { - // TODO(gab): Remove this method when all embedders have moved to - // GetWorkerThreadsTaskRunner(). - - // An implementation needs to be provided here because this is called by the - // default GetWorkerThreadsTaskRunner() implementation below. In practice - // however, all code either: - // - Overrides GetWorkerThreadsTaskRunner() (thus not making this call) -- - // i.e. all v8 code. - // - Overrides this method (thus not making this call) -- i.e. all - // unadapted embedders. - abort(); - } - - /** - * Returns a TaskRunner which can be used to post async tasks on a worker. - * This function should only be called from a foreground thread. - */ - virtual std::shared_ptr GetWorkerThreadsTaskRunner( - Isolate* isolate) { - // TODO(gab): Make this function abstract after it got implemented on all - // platforms. - return GetBackgroundTaskRunner(isolate); - } - - /** - * Schedules a task to be invoked on a background thread. |expected_runtime| - * indicates that the task will run a long time. The Platform implementation - * takes ownership of |task|. There is no guarantee about order of execution - * of tasks wrt order of scheduling, nor is there a guarantee about the - * thread the task will be run on. - */ - V8_DEPRECATE_SOON( - "ExpectedRuntime is deprecated, use CallOnWorkerThread() instead.", - virtual void CallOnBackgroundThread(Task* task, - ExpectedRuntime expected_runtime)) { - // An implementation needs to be provided here because this is called by the - // default implementation below. In practice however, all code either: - // - Overrides the new method (thus not making this call) -- i.e. all v8 - // code. - // - Overrides this method (thus not making this call) -- i.e. all - // unadapted embedders. - abort(); - } + Isolate* isolate) = 0; /** * Schedules a task to be invoked on a worker thread. - * TODO(gab): Make pure virtual when all embedders override this instead of - * CallOnBackgroundThread(). */ - virtual void CallOnWorkerThread(std::unique_ptr task) { - CallOnBackgroundThread(task.release(), kShortRunningTask); - } + virtual void CallOnWorkerThread(std::unique_ptr task) = 0; /** * Schedules a task that blocks the main thread to be invoked with @@ -397,6 +312,13 @@ class Platform { CallOnWorkerThread(std::move(task)); } + /** + * Schedules a task to be invoked on a worker thread after |delay_in_seconds| + * expires. + */ + virtual void CallDelayedOnWorkerThread(std::unique_ptr task, + double delay_in_seconds) = 0; + /** * Schedules a task to be invoked on a foreground thread wrt a specific * |isolate|. Tasks posted for the same isolate should be execute in order of @@ -422,14 +344,14 @@ class Platform { * The definition of "foreground" is opaque to V8. */ virtual void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) { - // TODO(ulan): Make this function abstract after V8 roll in Chromium. + // This must be overriden if |IdleTasksEnabled()|. + abort(); } /** * Returns true if idle tasks are enabled for the given |isolate|. */ virtual bool IdleTasksEnabled(Isolate* isolate) { - // TODO(ulan): Make this function abstract after V8 roll in Chromium. return false; } diff --git a/test-app/runtime/src/main/cpp/include/v8-profiler.h b/test-app/runtime/src/main/cpp/include/v8-profiler.h index 4250ca985..ca7b0c21b 100644 --- a/test-app/runtime/src/main/cpp/include/v8-profiler.h +++ b/test-app/runtime/src/main/cpp/include/v8-profiler.h @@ -54,7 +54,11 @@ namespace v8 { */ class V8_EXPORT TracingCpuProfiler { public: - static std::unique_ptr Create(Isolate*); + V8_DEPRECATED( + "The profiler is created automatically with the isolate.\n" + "No need to create it explicitly.", + static std::unique_ptr Create(Isolate*)); + virtual ~TracingCpuProfiler() = default; protected: @@ -274,6 +278,16 @@ class V8_EXPORT CpuProfile { void Delete(); }; +enum CpuProfilingMode { + // In the resulting CpuProfile tree, intermediate nodes in a stack trace + // (from the root to a leaf) will have line numbers that point to the start + // line of the function, rather than the line of the callsite of the child. + kLeafNodeLineNumbers, + // In the resulting CpuProfile tree, nodes are separated based on the line + // number of their callsite in their parent. + kCallerLineNumbers, +}; + /** * Interface for controlling CPU profiling. Instance of the * profiler can be created using v8::CpuProfiler::New method. @@ -317,6 +331,13 @@ class V8_EXPORT CpuProfiler { * |record_samples| parameter controls whether individual samples should * be recorded in addition to the aggregated tree. */ + void StartProfiling(Local title, CpuProfilingMode mode, + bool record_samples = false); + /** + * The same as StartProfiling above, but the CpuProfilingMode defaults to + * kLeafNodeLineNumbers mode, which was the previous default behavior of the + * profiler. + */ void StartProfiling(Local title, bool record_samples = false); /** @@ -639,7 +660,7 @@ class V8_EXPORT AllocationProfile { * Usage: * 1) Define derived class of EmbedderGraph::Node for embedder objects. * 2) Set the build embedder graph callback on the heap profiler using - * HeapProfiler::SetBuildEmbedderGraphCallback. + * HeapProfiler::AddBuildEmbedderGraphCallback. * 3) In the callback use graph->AddEdge(node1, node2) to add an edge from * node1 to node2. * 4) To represent references from/to V8 object, construct V8 nodes using @@ -693,11 +714,14 @@ class V8_EXPORT EmbedderGraph { virtual Node* AddNode(std::unique_ptr node) = 0; /** - * Adds an edge that represents a strong reference from the given node - * |from| to the given node |to|. The nodes must be added to the graph + * Adds an edge that represents a strong reference from the given + * node |from| to the given node |to|. The nodes must be added to the graph * before calling this function. + * + * If name is nullptr, the edge will have auto-increment indexes, otherwise + * it will be named accordingly. */ - virtual void AddEdge(Node* from, Node* to) = 0; + virtual void AddEdge(Node* from, Node* to, const char* name = nullptr) = 0; virtual ~EmbedderGraph() = default; }; @@ -747,6 +771,11 @@ class V8_EXPORT HeapProfiler { * The callback must not trigger garbage collection in V8. */ typedef void (*BuildEmbedderGraphCallback)(v8::Isolate* isolate, + v8::EmbedderGraph* graph, + void* data); + + /** TODO(addaleax): Remove */ + typedef void (*LegacyBuildEmbedderGraphCallback)(v8::Isolate* isolate, v8::EmbedderGraph* graph); /** Returns the number of snapshots taken. */ @@ -889,15 +918,22 @@ class V8_EXPORT HeapProfiler { /** Binds a callback to embedder's class ID. */ V8_DEPRECATED( - "Use SetBuildEmbedderGraphCallback to provide info about embedder nodes", + "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes", void SetWrapperClassInfoProvider(uint16_t class_id, WrapperInfoCallback callback)); V8_DEPRECATED( - "Use SetBuildEmbedderGraphCallback to provide info about embedder nodes", + "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes", void SetGetRetainerInfosCallback(GetRetainerInfosCallback callback)); - void SetBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback); + V8_DEPRECATE_SOON( + "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes", + void SetBuildEmbedderGraphCallback( + LegacyBuildEmbedderGraphCallback callback)); + void AddBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback, + void* data); + void RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback, + void* data); /** * Default value of persistent handle class ID. Must not be used to @@ -1005,6 +1041,76 @@ struct HeapStatsUpdate { uint32_t size; // New value of size field for the interval with this index. }; +#define CODE_EVENTS_LIST(V) \ + V(Builtin) \ + V(Callback) \ + V(Eval) \ + V(Function) \ + V(InterpretedFunction) \ + V(Handler) \ + V(BytecodeHandler) \ + V(LazyCompile) \ + V(RegExp) \ + V(Script) \ + V(Stub) + +/** + * Note that this enum may be extended in the future. Please include a default + * case if this enum is used in a switch statement. + */ +enum CodeEventType { + kUnknownType = 0 +#define V(Name) , k##Name##Type + CODE_EVENTS_LIST(V) +#undef V +}; + +/** + * Representation of a code creation event + */ +class V8_EXPORT CodeEvent { + public: + uintptr_t GetCodeStartAddress(); + size_t GetCodeSize(); + Local GetFunctionName(); + Local GetScriptName(); + int GetScriptLine(); + int GetScriptColumn(); + /** + * NOTE (mmarchini): We can't allocate objects in the heap when we collect + * existing code, and both the code type and the comment are not stored in the + * heap, so we return those as const char*. + */ + CodeEventType GetCodeType(); + const char* GetComment(); + + static const char* GetCodeEventTypeName(CodeEventType code_event_type); +}; + +/** + * Interface to listen to code creation events. + */ +class V8_EXPORT CodeEventHandler { + public: + /** + * Creates a new listener for the |isolate|. The isolate must be initialized. + * The listener object must be disposed after use by calling |Dispose| method. + * Multiple listeners can be created for the same isolate. + */ + explicit CodeEventHandler(Isolate* isolate); + virtual ~CodeEventHandler(); + + virtual void Handle(CodeEvent* code_event) = 0; + + void Enable(); + void Disable(); + + private: + CodeEventHandler(); + CodeEventHandler(const CodeEventHandler&); + CodeEventHandler& operator=(const CodeEventHandler&); + void* internal_listener_; +}; } // namespace v8 diff --git a/test-app/runtime/src/main/cpp/include/v8-version.h b/test-app/runtime/src/main/cpp/include/v8-version.h index 440a60686..57fbc6296 100644 --- a/test-app/runtime/src/main/cpp/include/v8-version.h +++ b/test-app/runtime/src/main/cpp/include/v8-version.h @@ -9,9 +9,9 @@ // NOTE these macros are used by some of the tool scripts and the build // system so their names cannot be changed without changing the scripts. #define V8_MAJOR_VERSION 6 -#define V8_MINOR_VERSION 7 -#define V8_BUILD_NUMBER 288 -#define V8_PATCH_LEVEL 46 +#define V8_MINOR_VERSION 9 +#define V8_BUILD_NUMBER 427 +#define V8_PATCH_LEVEL 23 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/test-app/runtime/src/main/cpp/include/v8.h b/test-app/runtime/src/main/cpp/include/v8.h index d685010c2..5bf0606f9 100644 --- a/test-app/runtime/src/main/cpp/include/v8.h +++ b/test-app/runtime/src/main/cpp/include/v8.h @@ -71,7 +71,6 @@ class BigIntObject; class Boolean; class BooleanObject; class Context; -class CpuProfiler; class Data; class Date; class External; @@ -146,6 +145,8 @@ class DeferredHandles; class Heap; class HeapObject; class Isolate; +class LocalEmbedderHeapTracer; +class NeverReadOnlySpaceObject; class Object; struct ScriptStreamingData; template class CustomArguments; @@ -154,8 +155,118 @@ class FunctionCallbackArguments; class GlobalHandles; namespace wasm { +class CompilationResultResolver; class StreamingDecoder; } // namespace wasm + +/** + * Configuration of tagging scheme. + */ +const int kApiPointerSize = sizeof(void*); // NOLINT +const int kApiDoubleSize = sizeof(double); // NOLINT +const int kApiIntSize = sizeof(int); // NOLINT +const int kApiInt64Size = sizeof(int64_t); // NOLINT + +// Tag information for HeapObject. +const int kHeapObjectTag = 1; +const int kWeakHeapObjectTag = 3; +const int kHeapObjectTagSize = 2; +const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1; + +// Tag information for Smi. +const int kSmiTag = 0; +const int kSmiTagSize = 1; +const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1; + +template +struct SmiTagging; + +template +V8_INLINE internal::Object* IntToSmi(int value) { + int smi_shift_bits = kSmiTagSize + kSmiShiftSize; + intptr_t tagged_value = + (static_cast(value) << smi_shift_bits) | kSmiTag; + return reinterpret_cast(tagged_value); +} + +// Smi constants for systems where tagged pointer is a 32-bit value. +template <> +struct SmiTagging<4> { + enum { kSmiShiftSize = 0, kSmiValueSize = 31 }; + static int SmiShiftSize() { + return kSmiShiftSize; + } + static int SmiValueSize() { + return kSmiValueSize; + } + V8_INLINE static int SmiToInt(const internal::Object* value) { + int shift_bits = kSmiTagSize + kSmiShiftSize; + // Throw away top 32 bits and shift down (requires >> to be sign extending). + return static_cast(reinterpret_cast(value)) >> shift_bits; + } + V8_INLINE static internal::Object* IntToSmi(int value) { + return internal::IntToSmi(value); + } + V8_INLINE static bool IsValidSmi(intptr_t value) { + // To be representable as an tagged small integer, the two + // most-significant bits of 'value' must be either 00 or 11 due to + // sign-extension. To check this we add 01 to the two + // most-significant bits, and check if the most-significant bit is 0 + // + // CAUTION: The original code below: + // bool result = ((value + 0x40000000) & 0x80000000) == 0; + // may lead to incorrect results according to the C language spec, and + // in fact doesn't work correctly with gcc4.1.1 in some cases: The + // compiler may produce undefined results in case of signed integer + // overflow. The computation must be done w/ unsigned ints. + return static_cast(value) + 0x40000000U < 0x80000000U; + } +}; + +// Smi constants for systems where tagged pointer is a 64-bit value. +template <> +struct SmiTagging<8> { + enum { kSmiShiftSize = 31, kSmiValueSize = 32 }; + static int SmiShiftSize() { + return kSmiShiftSize; + } + static int SmiValueSize() { + return kSmiValueSize; + } + V8_INLINE static int SmiToInt(const internal::Object* value) { + int shift_bits = kSmiTagSize + kSmiShiftSize; + // Shift down and throw away top 32 bits. + return static_cast(reinterpret_cast(value) >> shift_bits); + } + V8_INLINE static internal::Object* IntToSmi(int value) { + return internal::IntToSmi(value); + } + V8_INLINE static bool IsValidSmi(intptr_t value) { + // To be representable as a long smi, the value must be a 32-bit integer. + return (value == static_cast(value)); + } +}; + +#if V8_COMPRESS_POINTERS +static_assert( + kApiPointerSize == kApiInt64Size, + "Pointer compression can be enabled only for 64-bit architectures"); +typedef SmiTagging<4> PlatformSmiTagging; +#else +typedef SmiTagging PlatformSmiTagging; +#endif + +const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize; +const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize; +const int kSmiMinValue = (static_cast(-1)) << (kSmiValueSize - 1); +const int kSmiMaxValue = -(kSmiMinValue + 1); +constexpr bool SmiValuesAre31Bits() { + return kSmiValueSize == 31; +} +constexpr bool SmiValuesAre32Bits() { + return kSmiValueSize == 32; +} + } // namespace internal namespace debug { @@ -950,8 +1061,8 @@ class V8_EXPORT HandleScope { void operator delete[](void*, size_t); // Uses heap_object to obtain the current Isolate. - static internal::Object** CreateHandle(internal::HeapObject* heap_object, - internal::Object* value); + static internal::Object** CreateHandle( + internal::NeverReadOnlySpaceObject* heap_object, internal::Object* value); internal::Isolate* isolate_; internal::Object** prev_next_; @@ -987,6 +1098,11 @@ class V8_EXPORT EscapableHandleScope : public HandleScope { return Local(reinterpret_cast(slot)); } + template + V8_INLINE MaybeLocal EscapeMaybe(MaybeLocal value) { + return Escape(value.FromMaybe(Local())); + } + EscapableHandleScope(const EscapableHandleScope&) = delete; void operator=(const EscapableHandleScope&) = delete; @@ -1073,8 +1189,12 @@ class V8_EXPORT PrimitiveArray { public: static Local New(Isolate* isolate, int length); int Length() const; - void Set(int index, Local item); - Local Get(int index); + void Set(Isolate* isolate, int index, Local item); + Local Get(Isolate* isolate, int index); + + V8_DEPRECATE_SOON("Use Isolate version", + void Set(int index, Local item)); + V8_DEPRECATE_SOON("Use Isolate version", Local Get(int index)); }; /** @@ -1187,6 +1307,13 @@ class V8_EXPORT UnboundScript { static const int kNoScriptId = 0; }; +/** + * A compiled JavaScript module, not yet tied to a Context. + */ +class V8_EXPORT UnboundModuleScript { + // Only used as a container for code caching. +}; + /** * A location in JavaScript source. */ @@ -1290,6 +1417,14 @@ class V8_EXPORT Module { * The module's status must be at least kInstantiated. */ Local GetModuleNamespace(); + + /** + * Returns the corresponding context-unbound module script. + * + * The module must be unevaluated, i.e. its status must not be kEvaluating, + * kEvaluated or kErrored. + */ + Local GetUnboundModuleScript(); }; /** @@ -1432,6 +1567,10 @@ class V8_EXPORT ScriptCompiler { * more than two data chunks. The embedder can avoid this problem by always * returning at least 2 bytes of data. * + * When streaming UTF-16 data, V8 does not handle characters split between + * two data chunks. The embedder has to make sure that chunks have an even + * length. + * * If the embedder wants to cancel the streaming, they should make the next * GetMoreData call return 0. V8 will interpret it as end of data (and most * probably, parsing will fail). The streaming task will return as soon as @@ -1617,7 +1756,9 @@ class V8_EXPORT ScriptCompiler { * ECMAScript specification. */ static V8_WARN_UNUSED_RESULT MaybeLocal CompileModule( - Isolate* isolate, Source* source); + Isolate* isolate, Source* source, + CompileOptions options = kNoCompileOptions, + NoCacheReason no_cache_reason = kNoCacheNoReason); /** * Compile a function for a given context. This is equivalent to running @@ -1648,8 +1789,19 @@ 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 unbound_script, - Local source); + static CachedData* CreateCodeCache(Local unbound_script); + + /** + * Creates and returns code cache for the specified unbound_module_script. + * 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 unbound_module_script); + + V8_DEPRECATED("Source string is no longer required", + static CachedData* CreateCodeCache( + Local unbound_script, Local source)); /** * Creates and returns code cache for the specified function that was @@ -1657,8 +1809,11 @@ 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, - Local source); + static CachedData* CreateCodeCacheForFunction(Local function); + + V8_DEPRECATED("Source string is no longer required", + static CachedData* CreateCodeCacheForFunction( + Local function, Local source)); private: static V8_WARN_UNUSED_RESULT MaybeLocal CompileUnboundInternal( @@ -1780,7 +1935,9 @@ class V8_EXPORT StackTrace { /** * Returns a StackFrame at a particular index. */ - Local GetFrame(uint32_t index) const; + V8_DEPRECATE_SOON("Use Isolate version", + Local GetFrame(uint32_t index) const); + Local GetFrame(Isolate* isolate, uint32_t index) const; /** * Returns the number of StackFrames. @@ -1977,12 +2134,16 @@ class V8_EXPORT ValueSerializer { * If the memory cannot be allocated, nullptr should be returned. * |actual_size| will be ignored. It is assumed that |old_buffer| is still * valid in this case and has not been modified. + * + * The default implementation uses the stdlib's `realloc()` function. */ virtual void* ReallocateBufferMemory(void* old_buffer, size_t size, size_t* actual_size); /** * Frees a buffer allocated with |ReallocateBufferMemory|. + * + * The default implementation uses the stdlib's `free()` function. */ virtual void FreeBufferMemory(void* buffer); }; @@ -2010,9 +2171,9 @@ class V8_EXPORT ValueSerializer { /** * Returns the stored data (allocated using the delegate's - * AllocateBufferMemory) and its size. This serializer should not be used once - * the buffer is released. The contents are undefined if a previous write has - * failed. + * ReallocateBufferMemory) and its size. This serializer should not be used + * once the buffer is released. The contents are undefined if a previous write + * has failed. Ownership of the buffer is transferred to the caller. */ V8_WARN_UNUSED_RESULT std::pair Release(); @@ -2448,6 +2609,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 ToBigInt( Local context) const; V8_WARN_UNUSED_RESULT MaybeLocal ToBoolean( @@ -2597,8 +2763,9 @@ enum class NewStringType { */ class V8_EXPORT String : public Name { public: - static constexpr int kMaxLength = - sizeof(void*) == 4 ? (1 << 28) - 16 : (1 << 30) - 1 - 24; + static constexpr int kMaxLength = internal::kApiPointerSize == 4 + ? (1 << 28) - 16 + : internal::kSmiMaxValue / 2 - 24; enum Encoding { UNKNOWN_ENCODING = 0x1, @@ -2614,7 +2781,9 @@ class V8_EXPORT String : public Name { * Returns the number of bytes in the UTF-8 encoded * representation of this string. */ - int Utf8Length() const; + V8_DEPRECATE_SOON("Use Isolate version instead", int Utf8Length() const); + + int Utf8Length(Isolate* isolate) const; /** * Returns whether this string is known to contain only one byte data, @@ -2668,20 +2837,25 @@ class V8_EXPORT String : public Name { }; // 16-bit character codes. - int Write(uint16_t* buffer, - int start = 0, - int length = -1, + int Write(Isolate* isolate, uint16_t* buffer, int start = 0, int length = -1, int options = NO_OPTIONS) const; + V8_DEPRECATE_SOON("Use Isolate* version", + int Write(uint16_t* buffer, int start = 0, int length = -1, + int options = NO_OPTIONS) const); // One byte characters. - int WriteOneByte(uint8_t* buffer, - int start = 0, - int length = -1, - int options = NO_OPTIONS) const; + int WriteOneByte(Isolate* isolate, uint8_t* buffer, int start = 0, + int length = -1, int options = NO_OPTIONS) const; + V8_DEPRECATE_SOON("Use Isolate* version", + int WriteOneByte(uint8_t* buffer, int start = 0, + int length = -1, int options = NO_OPTIONS) + const); // UTF-8 encoded characters. - int WriteUtf8(char* buffer, - int length = -1, - int* nchars_ref = NULL, - int options = NO_OPTIONS) const; + int WriteUtf8(Isolate* isolate, char* buffer, int length = -1, + int* nchars_ref = NULL, int options = NO_OPTIONS) const; + V8_DEPRECATE_SOON("Use Isolate* version", + int WriteUtf8(char* buffer, int length = -1, + int* nchars_ref = NULL, + int options = NO_OPTIONS) const); /** * A zero length string. @@ -2847,7 +3021,11 @@ class V8_EXPORT String : public Name { * Creates a new string by concatenating the left and the right strings * passed in as parameters. */ - static Local Concat(Local left, Local right); + static Local Concat(Isolate* isolate, Local left, + Local right); + static V8_DEPRECATE_SOON("Use Isolate* version", + Local Concat(Local left, + Local right)); /** * Creates a new external string using the data defined in the given @@ -3123,6 +3301,48 @@ class V8_EXPORT Uint32 : public Integer { class V8_EXPORT BigInt : public Primitive { public: static Local New(Isolate* isolate, int64_t value); + static Local NewFromUnsigned(Isolate* isolate, uint64_t value); + /** + * Creates a new BigInt object using a specified sign bit and a + * specified list of digits/words. + * The resulting number is calculated as: + * + * (-1)^sign_bit * (words[0] * (2^64)^0 + words[1] * (2^64)^1 + ...) + */ + static MaybeLocal NewFromWords(Local context, int sign_bit, + int word_count, const uint64_t* words); + + /** + * Returns the value of this BigInt as an unsigned 64-bit integer. + * If `lossless` is provided, it will reflect whether the return value was + * truncated or wrapped around. In particular, it is set to `false` if this + * BigInt is negative. + */ + uint64_t Uint64Value(bool* lossless = nullptr) const; + + /** + * Returns the value of this BigInt as a signed 64-bit integer. + * If `lossless` is provided, it will reflect whether this BigInt was + * truncated or not. + */ + int64_t Int64Value(bool* lossless = nullptr) const; + + /** + * Returns the number of 64-bit words needed to store the result of + * ToWordsArray(). + */ + int WordCount() const; + + /** + * Writes the contents of this BigInt to a specified memory location. + * `sign_bit` must be provided and will be set to 1 if this BigInt is + * negative. + * `*word_count` has to be initialized to the length of the `words` array. + * Upon return, it will be set to the actual number of words that would + * be needed to store this BigInt (i.e. the return value of `WordCount()`). + */ + void ToWordsArray(int* sign_bit, int* word_count, uint64_t* words) const; + V8_INLINE static BigInt* Cast(v8::Value* obj); private: @@ -3630,6 +3850,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 (without + * scheduling an exception). + */ + MaybeLocal PreviewEntries(bool* is_key_value); + static Local New(Isolate* isolate); V8_INLINE static Object* Cast(Value* obj); @@ -3982,6 +4213,15 @@ class V8_EXPORT Function : public Object { return NewInstance(context, 0, nullptr); } + /** + * When side effect checks are enabled, passing kHasNoSideEffect allows the + * constructor to be invoked without throwing. Calls made within the + * constructor are still checked. + */ + V8_WARN_UNUSED_RESULT MaybeLocal NewInstanceWithSideEffectType( + Local context, int argc, Local argv[], + SideEffectType side_effect_type = SideEffectType::kHasSideEffect) const; + V8_DEPRECATE_SOON("Use maybe version", Local Call(Local recv, int argc, Local argv[])); @@ -4236,10 +4476,29 @@ class V8_EXPORT Proxy : public Object { class V8_EXPORT WasmCompiledModule : public Object { public: typedef std::pair, size_t> SerializedModule; - /** - * A buffer that is owned by the caller. - */ - typedef std::pair CallerOwnedBuffer; + +// The COMMA macro allows us to use ',' inside of the V8_DEPRECATE_SOON macro. +#define COMMA , + V8_DEPRECATE_SOON( + "Use BufferReference.", + typedef std::pair CallerOwnedBuffer); +#undef COMMA + + /** + * A unowned reference to a byte buffer. + */ + struct BufferReference { + const uint8_t* start; + size_t size; + BufferReference(const uint8_t* start, size_t size) + : start(start), size(size) {} + // Temporarily allow conversion to and from CallerOwnedBuffer. + V8_DEPRECATE_SOON( + "Use BufferReference directly.", + inline BufferReference(CallerOwnedBuffer)); // NOLINT(runtime/explicit) + V8_DEPRECATE_SOON("Use BufferReference directly.", + inline operator CallerOwnedBuffer()); + }; /** * An opaque, native heap object for transferring wasm modules. It @@ -4256,7 +4515,7 @@ class V8_EXPORT WasmCompiledModule : public Object { private: typedef std::pair, size_t> OwnedBuffer; friend class WasmCompiledModule; - TransferrableModule(OwnedBuffer&& code, OwnedBuffer&& bytes) + TransferrableModule(OwnedBuffer code, OwnedBuffer bytes) : compiled_code(std::move(code)), wire_bytes(std::move(bytes)) {} OwnedBuffer compiled_code = {nullptr, 0}; @@ -4280,7 +4539,9 @@ class V8_EXPORT WasmCompiledModule : public Object { /** * Get the wasm-encoded bytes that were used to compile this module. */ - Local GetWasmWireBytes(); + BufferReference GetWasmWireBytesRef(); + V8_DEPRECATE_SOON("Use GetWasmWireBytesRef version.", + Local GetWasmWireBytes()); /** * Serialize the compiled module. The serialized data does not include the @@ -4293,18 +4554,18 @@ class V8_EXPORT WasmCompiledModule : public Object { * uncompiled bytes. */ static MaybeLocal DeserializeOrCompile( - Isolate* isolate, const CallerOwnedBuffer& serialized_module, - const CallerOwnedBuffer& wire_bytes); + Isolate* isolate, BufferReference serialized_module, + BufferReference wire_bytes); V8_INLINE static WasmCompiledModule* Cast(Value* obj); private: static MaybeLocal Deserialize( - Isolate* isolate, const CallerOwnedBuffer& serialized_module, - const CallerOwnedBuffer& wire_bytes); + Isolate* isolate, BufferReference serialized_module, + BufferReference wire_bytes); static MaybeLocal Compile(Isolate* isolate, const uint8_t* start, size_t length); - static CallerOwnedBuffer AsCallerOwned( + static BufferReference AsReference( const TransferrableModule::OwnedBuffer& buff) { return {buff.first.get(), buff.second}; } @@ -4313,6 +4574,61 @@ class V8_EXPORT WasmCompiledModule : public Object { static void CheckCast(Value* obj); }; +// TODO(clemensh): Remove after M69 branch. +WasmCompiledModule::BufferReference::BufferReference( + WasmCompiledModule::CallerOwnedBuffer buf) + : BufferReference(buf.first, buf.second) {} +WasmCompiledModule::BufferReference:: +operator WasmCompiledModule::CallerOwnedBuffer() { + return {start, size}; +} + +/** + * The V8 interface for WebAssembly streaming compilation. When streaming + * compilation is initiated, V8 passes a {WasmStreaming} object to the embedder + * such that the embedder can pass the input butes for streaming compilation to + * V8. + */ +class V8_EXPORT WasmStreaming final { + public: + class WasmStreamingImpl; + + WasmStreaming(std::unique_ptr impl); + + ~WasmStreaming(); + + /** + * Pass a new chunck of bytes to WebAssembly streaming compilation. + * The buffer passed into {OnBytesReceived} is owned by the caller. + */ + void OnBytesReceived(const uint8_t* bytes, size_t size); + + /** + * {Finish} should be called after all received bytes where passed to + * {OnBytesReceived} to tell V8 that there will be no more bytes. {Finish} + * does not have to be called after {Abort} has been called already. + */ + void Finish(); + + /** + * Abort streaming compilation. If {exception} has a value, then the promise + * associated with streaming compilation is rejected with that value. If + * {exception} does not have value, the promise does not get rejected. + */ + void Abort(MaybeLocal exception); + + /** + * Unpacks a {WasmStreaming} object wrapped in a {Managed} for the embedder. + * Since the embedder is on the other side of the API, it cannot unpack the + * {Managed} itself. + */ + static std::shared_ptr Unpack(Isolate* isolate, + Local value); + + private: + std::unique_ptr impl_; +}; + // TODO(mtrofin): when streaming compilation is done, we can rename this // to simply WasmModuleObjectBuilder class V8_EXPORT WasmModuleObjectBuilderStreaming final { @@ -4334,8 +4650,6 @@ class V8_EXPORT WasmModuleObjectBuilderStreaming final { ~WasmModuleObjectBuilderStreaming(); private: - typedef std::pair, size_t> Buffer; - WasmModuleObjectBuilderStreaming(const WasmModuleObjectBuilderStreaming&) = delete; WasmModuleObjectBuilderStreaming(WasmModuleObjectBuilderStreaming&&) = @@ -4358,8 +4672,6 @@ class V8_EXPORT WasmModuleObjectBuilderStreaming final { #else Persistent promise_; #endif - std::vector received_buffers_; - size_t total_size_ = 0; std::shared_ptr streaming_decoder_; }; @@ -4618,8 +4930,7 @@ class V8_EXPORT TypedArray : public ArrayBufferView { /* * The largest typed array size that can be constructed using New. */ - static constexpr size_t kMaxLength = - sizeof(void*) == 4 ? (1u << 30) - 1 : (1u << 31) - 1; + static constexpr size_t kMaxLength = internal::kSmiMaxValue; /** * Number of elements in this typed array @@ -5045,7 +5356,9 @@ class V8_EXPORT BooleanObject : public Object { */ class V8_EXPORT StringObject : public Object { public: - static Local New(Local value); + static Local New(Isolate* isolate, Local value); + static V8_DEPRECATE_SOON("Use Isolate* version", + Local New(Local value)); Local ValueOf() const; @@ -5212,22 +5525,25 @@ class V8_EXPORT Template : public Data { // TODO(dcarney): gcc can't handle Local below Local data = Local(), PropertyAttribute attribute = None, Local signature = Local(), - AccessControl settings = DEFAULT); + AccessControl settings = DEFAULT, + SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect); void SetNativeDataProperty( Local name, AccessorNameGetterCallback getter, AccessorNameSetterCallback setter = 0, // TODO(dcarney): gcc can't handle Local below Local data = Local(), PropertyAttribute attribute = None, Local signature = Local(), - AccessControl settings = DEFAULT); + AccessControl settings = DEFAULT, + SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect); /** * Like SetNativeDataProperty, but V8 will replace the native data property * with a real data property on first access. */ - void SetLazyDataProperty(Local name, AccessorNameGetterCallback getter, - Local data = Local(), - PropertyAttribute attribute = None); + void SetLazyDataProperty( + Local name, AccessorNameGetterCallback getter, + Local data = Local(), PropertyAttribute attribute = None, + SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect); /** * During template instantiation, sets the value with the intrinsic property @@ -5951,12 +6267,14 @@ class V8_EXPORT ObjectTemplate : public Template { Local name, AccessorGetterCallback getter, AccessorSetterCallback setter = 0, Local data = Local(), AccessControl settings = DEFAULT, PropertyAttribute attribute = None, - Local signature = Local()); + Local signature = Local(), + SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect); void SetAccessor( Local name, AccessorNameGetterCallback getter, AccessorNameSetterCallback setter = 0, Local data = Local(), AccessControl settings = DEFAULT, PropertyAttribute attribute = None, - Local signature = Local()); + Local signature = Local(), + SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect); /** * Sets a named property handler on the object template. @@ -6162,7 +6480,8 @@ class V8_EXPORT AccessorSignature : public Data { // --- Extensions --- - +V8_DEPRECATE_SOON("Implementation detail", + class ExternalOneByteStringResourceImpl); class V8_EXPORT ExternalOneByteStringResourceImpl : public String::ExternalOneByteStringResource { public: @@ -6193,7 +6512,9 @@ class V8_EXPORT Extension { // NOLINT int dep_count = 0, const char** deps = 0, int source_length = -1); - virtual ~Extension() { } + virtual ~Extension() { + delete source_; + } virtual Local GetNativeFunctionTemplate( Isolate* isolate, Local name) { return Local(); @@ -6206,7 +6527,7 @@ class V8_EXPORT Extension { // NOLINT return source_length_; } const String::ExternalOneByteStringResource* source() const { - return &source_; + return source_; } int dependency_count() { return dep_count_; @@ -6228,7 +6549,7 @@ class V8_EXPORT Extension { // NOLINT private: const char* name_; size_t source_length_; // expected to initialize before source_ - ExternalOneByteStringResourceImpl source_; + String::ExternalOneByteStringResource* source_; int dep_count_; const char** deps_; bool auto_enable_; @@ -6465,7 +6786,9 @@ typedef void (*PromiseHook)(PromiseHookType type, Local promise, // --- Promise Reject Callback --- enum PromiseRejectEvent { kPromiseRejectWithNoHandler = 0, - kPromiseHandlerAddedAfterReject = 1 + kPromiseHandlerAddedAfterReject = 1, + kPromiseRejectAfterResolved = 2, + kPromiseResolveAfterResolved = 3, }; class PromiseRejectMessage { @@ -6576,6 +6899,9 @@ typedef bool (*AllowWasmCodeGenerationCallback)(Local context, // by the embedder. Example: WebAssembly.{compile|instantiate}Streaming --- typedef void (*ApiImplementationCallback)(const FunctionCallbackInfo&); +// --- Callback for WebAssembly.compileStreaming --- +typedef void (*WasmStreamingCallback)(const FunctionCallbackInfo&); + // --- Garbage Collection Callbacks --- /** @@ -6762,10 +7088,14 @@ class V8_EXPORT HeapCodeStatistics { size_t bytecode_and_metadata_size() { return bytecode_and_metadata_size_; } + size_t external_script_source_size() { + return external_script_source_size_; + } private: size_t code_and_metadata_size_; size_t bytecode_and_metadata_size_; + size_t external_script_source_size_; friend class Isolate; }; @@ -6858,6 +7188,8 @@ struct JitCodeEvent { // New location of instructions. Only valid for CODE_MOVED. void* new_code_start; }; + + Isolate* isolate; }; /** @@ -6979,6 +7311,14 @@ class V8_EXPORT EmbedderHeapTracer { virtual bool AdvanceTracing(double deadline_in_ms, AdvanceTracingActions actions) = 0; + /* + * Returns true if there no more tracing work to be done (see AdvanceTracing) + * and false otherwise. + */ + virtual bool IsTracingDone() { + return NumberOfWrappersToTrace() == 0; + } + /** * Called at the end of a GC cycle. * @@ -7000,15 +7340,39 @@ class V8_EXPORT EmbedderHeapTracer { */ virtual void AbortTracing() = 0; + /* + * Called by the embedder to request immediaet finalization of the currently + * running tracing phase that has been started with TracePrologue and not + * yet finished with TraceEpilogue. + * + * Will be a noop when currently not in tracing. + * + * This is an experimental feature. + */ + void FinalizeTracing(); + + /* + * Returns the v8::Isolate this tracer is attached too and |nullptr| if it + * is not attached to any v8::Isolate. + */ + v8::Isolate* isolate() const { + return isolate_; + } + /** * Returns the number of wrappers that are still to be traced by the embedder. */ + V8_DEPRECATE_SOON("Use IsTracingDone", virtual size_t NumberOfWrappersToTrace() { return 0; - } + }); protected: virtual ~EmbedderHeapTracer() = default; + + v8::Isolate* isolate_ = nullptr; + + friend class internal::LocalEmbedderHeapTracer; }; /** @@ -7067,7 +7431,8 @@ class V8_EXPORT Isolate { add_histogram_sample_callback(nullptr), array_buffer_allocator(nullptr), external_references(nullptr), - allow_atomics_wait(true) {} + allow_atomics_wait(true), + only_terminate_in_safe_scope(false) {} /** * The optional entry_hook allows the host application to provide the @@ -7130,6 +7495,11 @@ class V8_EXPORT Isolate { * this isolate. This can also be configured via SetAllowAtomicsWait. */ bool allow_atomics_wait; + + /** + * Termination is postponed when there is no active SafeForTerminationScope. + */ + bool only_terminate_in_safe_scope; }; @@ -7216,6 +7586,24 @@ class V8_EXPORT Isolate { internal::Isolate* const isolate_; }; + /** + * This scope allows terminations inside direct V8 API calls and forbid them + * inside any recursice API calls without explicit SafeForTerminationScope. + */ + class V8_EXPORT SafeForTerminationScope { + public: + explicit SafeForTerminationScope(v8::Isolate* isolate); + ~SafeForTerminationScope(); + + // Prevent copying of Scope objects. + SafeForTerminationScope(const SafeForTerminationScope&) = delete; + SafeForTerminationScope& operator=(const SafeForTerminationScope&) = delete; + + private: + internal::Isolate* isolate_; + bool prev_value_; + }; + /** * Types of garbage collections that can be requested via * RequestGarbageCollectionForTesting. @@ -7279,6 +7667,8 @@ class V8_EXPORT Isolate { kErrorStackTraceLimit = 45, kWebAssemblyInstantiation = 46, kDeoptimizerDisableSpeculation = 47, + kArrayPrototypeSortJSArrayModifiedPrototype = 48, + kFunctionTokenOffsetTooLongForToString = 49, // If you add new values here, you'll also need to update Chromium's: // web_feature.mojom, UseCounterCallback.cpp, and enums.xml. V8 changes to @@ -7299,6 +7689,26 @@ class V8_EXPORT Isolate { typedef void (*UseCounterCallback)(Isolate* isolate, UseCounterFeature feature); + /** + * Allocates a new isolate but does not initialize it. Does not change the + * currently entered isolate. + * + * Only Isolate::GetData() and Isolate::SetData(), which access the + * embedder-controlled parts of the isolate, are allowed to be called on the + * uninitialized isolate. To initialize the isolate, call + * Isolate::Initialize(). + * + * When an isolate is no longer used its resources should be freed + * by calling Dispose(). Using the delete operator is not allowed. + * + * V8::Initialize() must have run prior to this. + */ + static Isolate* Allocate(); + + /** + * Initialize an Isolate previously allocated by Isolate::Allocate(). + */ + static void Initialize(Isolate* isolate, const CreateParams& params); /** * Creates a new isolate. Does not change the currently entered @@ -7514,15 +7924,7 @@ class V8_EXPORT Isolate { HeapProfiler* GetHeapProfiler(); /** - * Returns CPU profiler for this isolate. Will return NULL unless the isolate - * is initialized. It is the embedder's responsibility to stop all CPU - * profiling activities if it has started any. - */ - V8_DEPRECATED("CpuProfiler should be created with CpuProfiler::New call.", - CpuProfiler* GetCpuProfiler()); - - /** - * Tells the CPU profiler whether the embedder is idle. + * Tells the VM whether the embedder is idle or not. */ void SetIdle(bool is_idle); @@ -7601,6 +8003,85 @@ class V8_EXPORT Isolate { */ void SetEmbedderHeapTracer(EmbedderHeapTracer* tracer); + /** + * Use for |AtomicsWaitCallback| to indicate the type of event it receives. + */ + enum class AtomicsWaitEvent { + /** Indicates that this call is happening before waiting. */ + kStartWait, + /** `Atomics.wait()` finished because of an `Atomics.wake()` call. */ + kWokenUp, + /** `Atomics.wait()` finished because it timed out. */ + kTimedOut, + /** `Atomics.wait()` was interrupted through |TerminateExecution()|. */ + kTerminatedExecution, + /** `Atomics.wait()` was stopped through |AtomicsWaitWakeHandle|. */ + kAPIStopped, + /** `Atomics.wait()` did not wait, as the initial condition was not met. */ + kNotEqual + }; + + /** + * Passed to |AtomicsWaitCallback| as a means of stopping an ongoing + * `Atomics.wait` call. + */ + class V8_EXPORT AtomicsWaitWakeHandle { + public: + /** + * Stop this `Atomics.wait()` call and call the |AtomicsWaitCallback| + * with |kAPIStopped|. + * + * This function may be called from another thread. The caller has to ensure + * through proper synchronization that it is not called after + * the finishing |AtomicsWaitCallback|. + * + * Note that the ECMAScript specification does not plan for the possibility + * of wakeups that are neither coming from a timeout or an `Atomics.wake()` + * call, so this may invalidate assumptions made by existing code. + * The embedder may accordingly wish to schedule an exception in the + * finishing |AtomicsWaitCallback|. + */ + void Wake(); + }; + + /** + * Embedder callback for `Atomics.wait()` that can be added through + * |SetAtomicsWaitCallback|. + * + * This will be called just before starting to wait with the |event| value + * |kStartWait| and after finishing waiting with one of the other + * values of |AtomicsWaitEvent| inside of an `Atomics.wait()` call. + * + * |array_buffer| will refer to the underlying SharedArrayBuffer, + * |offset_in_bytes| to the location of the waited-on memory address inside + * the SharedArrayBuffer. + * + * |value| and |timeout_in_ms| will be the values passed to + * the `Atomics.wait()` call. If no timeout was used, |timeout_in_ms| + * will be `INFINITY`. + * + * In the |kStartWait| callback, |stop_handle| will be an object that + * is only valid until the corresponding finishing callback and that + * can be used to stop the wait process while it is happening. + * + * This callback may schedule exceptions, *unless* |event| is equal to + * |kTerminatedExecution|. + */ + typedef void (*AtomicsWaitCallback)(AtomicsWaitEvent event, + Local array_buffer, + size_t offset_in_bytes, int32_t value, + double timeout_in_ms, + AtomicsWaitWakeHandle* stop_handle, + void* data); + + /** + * Set a new |AtomicsWaitCallback|. This overrides an earlier + * |AtomicsWaitCallback|, if there was any. If |callback| is nullptr, + * this unsets the callback. |data| will be passed to the callback + * as its last parameter. + */ + void SetAtomicsWaitCallback(AtomicsWaitCallback callback, void* data); + /** * Enables the host application to receive a notification after a * garbage collection. Allocations are allowed in the callback function, @@ -7854,6 +8335,18 @@ class V8_EXPORT Isolate { */ void IsolateInBackgroundNotification(); + /** + * Optional notification which will enable the memory savings mode. + * V8 uses this notification to guide heuristics which may result in a + * smaller memory footprint at the cost of reduced runtime performance. + */ + void EnableMemorySavingsMode(); + + /** + * Optional notification which will disable the memory savings mode. + */ + void DisableMemorySavingsMode(); + /** * Optional notification to tell V8 the current performance requirements * of the embedder based on RAIL. @@ -7977,6 +8470,8 @@ class V8_EXPORT Isolate { void SetWasmCompileStreamingCallback(ApiImplementationCallback callback); + void SetWasmStreamingCallback(WasmStreamingCallback callback); + /** * Check if V8 is dead and therefore unusable. This is the case after * fatal errors such as out-of-memory situations. @@ -8147,7 +8642,9 @@ class V8_EXPORT V8 { * Returns { NULL, 0 } on failure. * The caller acquires ownership of the data array in the return value. */ - static StartupData CreateSnapshotDataBlob(const char* embedded_source = NULL); + V8_DEPRECATED("Use SnapshotCreator", + static StartupData CreateSnapshotDataBlob( + const char* embedded_source = NULL)); /** * Bootstrap an isolate and a context from the cold startup blob, run the @@ -8157,8 +8654,9 @@ class V8_EXPORT V8 { * The caller acquires ownership of the data array in the return value. * The argument startup blob is untouched. */ - static StartupData WarmUpSnapshotDataBlob(StartupData cold_startup_blob, - const char* warmup_source); + V8_DEPRECATED("Use SnapshotCreator", + static StartupData WarmUpSnapshotDataBlob( + StartupData cold_startup_blob, const char* warmup_source)); /** Set the callback to invoke in case of Dcheck failures. */ static void SetDcheckErrorHandler(DcheckErrorCallback that); @@ -8353,6 +8851,18 @@ class V8_EXPORT SnapshotCreator { public: enum class FunctionCodeHandling { kClear, kKeep }; + /** + * Initialize and enter an isolate, and set it up for serialization. + * The isolate is either created from scratch or from an existing snapshot. + * The caller keeps ownership of the argument snapshot. + * \param existing_blob existing snapshot from which to create this one. + * \param external_references a null-terminated array of external references + * that must be equivalent to CreateParams::external_references. + */ + SnapshotCreator(Isolate* isolate, + const intptr_t* external_references = nullptr, + StartupData* existing_blob = nullptr); + /** * Create and enter an isolate, and set it up for serialization. * The isolate is either created from scratch or from an existing snapshot. @@ -9141,97 +9651,6 @@ class V8_EXPORT Locker { namespace internal { -const int kApiPointerSize = sizeof(void*); // NOLINT -const int kApiIntSize = sizeof(int); // NOLINT -const int kApiInt64Size = sizeof(int64_t); // NOLINT - -// Tag information for HeapObject. -const int kHeapObjectTag = 1; -const int kWeakHeapObjectTag = 3; -const int kHeapObjectTagSize = 2; -const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1; - -// Tag information for Smi. -const int kSmiTag = 0; -const int kSmiTagSize = 1; -const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1; - -template struct SmiTagging; - -template -V8_INLINE internal::Object* IntToSmi(int value) { - int smi_shift_bits = kSmiTagSize + kSmiShiftSize; - uintptr_t tagged_value = - (static_cast(value) << smi_shift_bits) | kSmiTag; - return reinterpret_cast(tagged_value); -} - -// Smi constants for 32-bit systems. -template <> struct SmiTagging<4> { - enum { kSmiShiftSize = 0, kSmiValueSize = 31 }; - static int SmiShiftSize() { - return kSmiShiftSize; - } - static int SmiValueSize() { - return kSmiValueSize; - } - V8_INLINE static int SmiToInt(const internal::Object* value) { - int shift_bits = kSmiTagSize + kSmiShiftSize; - // Throw away top 32 bits and shift down (requires >> to be sign extending). - return static_cast(reinterpret_cast(value)) >> shift_bits; - } - V8_INLINE static internal::Object* IntToSmi(int value) { - return internal::IntToSmi(value); - } - V8_INLINE static bool IsValidSmi(intptr_t value) { - // To be representable as an tagged small integer, the two - // most-significant bits of 'value' must be either 00 or 11 due to - // sign-extension. To check this we add 01 to the two - // most-significant bits, and check if the most-significant bit is 0 - // - // CAUTION: The original code below: - // bool result = ((value + 0x40000000) & 0x80000000) == 0; - // may lead to incorrect results according to the C language spec, and - // in fact doesn't work correctly with gcc4.1.1 in some cases: The - // compiler may produce undefined results in case of signed integer - // overflow. The computation must be done w/ unsigned ints. - return static_cast(value + 0x40000000U) < 0x80000000U; - } -}; - -// Smi constants for 64-bit systems. -template <> struct SmiTagging<8> { - enum { kSmiShiftSize = 31, kSmiValueSize = 32 }; - static int SmiShiftSize() { - return kSmiShiftSize; - } - static int SmiValueSize() { - return kSmiValueSize; - } - V8_INLINE static int SmiToInt(const internal::Object* value) { - int shift_bits = kSmiTagSize + kSmiShiftSize; - // Shift down and throw away top 32 bits. - return static_cast(reinterpret_cast(value) >> shift_bits); - } - V8_INLINE static internal::Object* IntToSmi(int value) { - return internal::IntToSmi(value); - } - V8_INLINE static bool IsValidSmi(intptr_t value) { - // To be representable as a long smi, the value must be a 32-bit integer. - return (value == static_cast(value)); - } -}; - -typedef SmiTagging PlatformSmiTagging; -const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize; -const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize; -V8_INLINE static bool SmiValuesAre31Bits() { - return kSmiValueSize == 31; -} -V8_INLINE static bool SmiValuesAre32Bits() { - return kSmiValueSize == 32; -} - /** * This class exports constants and functionality from within v8 that * is necessary to implement inline functions in the v8 api. Don't @@ -9245,7 +9664,7 @@ class Internals { static const int kMapInstanceTypeOffset = 1 * kApiPointerSize + kApiIntSize; static const int kStringResourceOffset = 3 * kApiPointerSize; - static const int kOddballKindOffset = 4 * kApiPointerSize + sizeof(double); + static const int kOddballKindOffset = 4 * kApiPointerSize + kApiDoubleSize; static const int kForeignAddressOffset = kApiPointerSize; static const int kJSObjectHeaderSize = 3 * kApiPointerSize; static const int kFixedArrayHeaderSize = 2 * kApiPointerSize; @@ -9968,7 +10387,6 @@ AccessorSignature* AccessorSignature::Cast(Data* data) { Local Object::GetInternalField(int index) { #ifndef V8_ENABLE_CHECKS typedef internal::Object O; - typedef internal::HeapObject HO; typedef internal::Internals I; O* obj = *reinterpret_cast(this); // Fast path: If the object is a plain JSObject, which is the common case, we @@ -9979,7 +10397,8 @@ Local Object::GetInternalField(int index) { instance_type == I::kJSSpecialApiObjectType) { int offset = I::kJSObjectHeaderSize + (internal::kApiPointerSize * index); O* value = I::ReadField(obj, offset); - O** result = HandleScope::CreateHandle(reinterpret_cast(obj), value); + O** result = HandleScope::CreateHandle( + reinterpret_cast(obj), value); return Local(reinterpret_cast(result)); } #endif @@ -10635,9 +11054,8 @@ int64_t Isolate::AdjustAmountOfExternalAllocatedMemory( Local Context::GetEmbedderData(int index) { #ifndef V8_ENABLE_CHECKS typedef internal::Object O; - typedef internal::HeapObject HO; typedef internal::Internals I; - HO* context = *reinterpret_cast(this); + auto* context = *reinterpret_cast(this); O** result = HandleScope::CreateHandle(context, I::ReadEmbedderData(this, index)); return Local(reinterpret_cast(result)); diff --git a/test-app/runtime/src/main/cpp/v8_inspector/src/allocation.h b/test-app/runtime/src/main/cpp/v8_inspector/src/allocation.h index b210f43cc..83eb9919d 100644 --- a/test-app/runtime/src/main/cpp/v8_inspector/src/allocation.h +++ b/test-app/runtime/src/main/cpp/v8_inspector/src/allocation.h @@ -79,10 +79,10 @@ char* StrNDup(const char* str, int n); // and free. Used as the default policy for lists. class FreeStoreAllocationPolicy { public: - INLINE(void* New(size_t size)) { + V8_INLINE void* New(size_t size) { return Malloced::New(size); } - INLINE(static void Delete(void* p)) { + V8_INLINE static void Delete(void* p) { Malloced::Delete(p); } }; @@ -138,6 +138,10 @@ V8_WARN_UNUSED_RESULT bool ReleasePages(void* address, size_t size, V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT bool SetPermissions(void* address, size_t size, PageAllocator::Permission access); +inline bool SetPermissions(Address address, size_t size, + PageAllocator::Permission access) { + return SetPermissions(reinterpret_cast(address), size, access); +} // Convenience function that allocates a single system page with read and write // permissions. |address| is a hint. Returns the base address of the memory and @@ -163,7 +167,8 @@ class V8_EXPORT_PRIVATE VirtualMemory { // Construct a virtual memory by assigning it some already mapped address // and size. - VirtualMemory(void* address, size_t size) : address_(address), size_(size) {} + VirtualMemory(Address address, size_t size) + : address_(address), size_(size) {} // Releases the reserved memory, if any, controlled by this VirtualMemory // object. @@ -171,7 +176,7 @@ class V8_EXPORT_PRIVATE VirtualMemory { // Returns whether the memory has been reserved. bool IsReserved() const { - return address_ != nullptr; + return address_ != kNullAddress; } // Initialize or resets an embedded VirtualMemory object. @@ -181,15 +186,14 @@ class V8_EXPORT_PRIVATE VirtualMemory { // If the memory was reserved with an alignment, this address is not // necessarily aligned. The user might need to round it up to a multiple of // the alignment to get the start of the aligned block. - void* address() const { + Address address() const { DCHECK(IsReserved()); return address_; } - void* end() const { + Address end() const { DCHECK(IsReserved()); - return reinterpret_cast(reinterpret_cast(address_) + - size_); + return address_ + size_; } // Returns the size of the reserved memory. The returned value is only @@ -202,11 +206,11 @@ class V8_EXPORT_PRIVATE VirtualMemory { // Sets permissions according to the access argument. address and size must be // multiples of CommitPageSize(). Returns true on success, otherwise false. - bool SetPermissions(void* address, size_t size, + bool SetPermissions(Address address, size_t size, PageAllocator::Permission access); // Releases memory after |free_start|. Returns the number of bytes released. - size_t Release(void* free_start); + size_t Release(Address free_start); // Frees all memory. void Free(); @@ -215,15 +219,12 @@ class V8_EXPORT_PRIVATE VirtualMemory { // The old object is no longer functional (IsReserved() returns false). void TakeControl(VirtualMemory* from); - bool InVM(void* address, size_t size) { - return (reinterpret_cast(address_) <= - reinterpret_cast(address)) && - ((reinterpret_cast(address_) + size_) >= - (reinterpret_cast(address) + size)); + bool InVM(Address address, size_t size) { + return (address_ <= address) && ((address_ + size_) >= (address + size)); } private: - void* address_; // Start address of the virtual memory. + Address address_; // Start address of the virtual memory. size_t size_; // Size of the virtual memory. }; diff --git a/test-app/runtime/src/main/cpp/v8_inspector/src/base/atomic-utils.h b/test-app/runtime/src/main/cpp/v8_inspector/src/base/atomic-utils.h index 80d4db083..ce1ba3c38 100644 --- a/test-app/runtime/src/main/cpp/v8_inspector/src/base/atomic-utils.h +++ b/test-app/runtime/src/main/cpp/v8_inspector/src/base/atomic-utils.h @@ -14,50 +14,7 @@ namespace v8 { namespace base { -template -class AtomicNumber { - public: - AtomicNumber() : value_(0) {} - explicit AtomicNumber(T initial) : value_(initial) {} - - // Returns the value after incrementing. - V8_INLINE T Increment(T increment) { - return static_cast(base::Barrier_AtomicIncrement( - &value_, static_cast(increment))); - } - - // Returns the value after decrementing. - V8_INLINE T Decrement(T decrement) { - return static_cast(base::Barrier_AtomicIncrement( - &value_, -static_cast(decrement))); - } - - V8_INLINE T Value() const { - return static_cast(base::Acquire_Load(&value_)); - } - - V8_INLINE void SetValue(T new_value) { - base::Release_Store(&value_, static_cast(new_value)); - } - - V8_INLINE T operator=(T value) { - SetValue(value); - return value; - } - - V8_INLINE T operator+=(T value) { - return Increment(value); - } - V8_INLINE T operator-=(T value) { - return Decrement(value); - } - - private: - STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); - - base::AtomicWord value_; -}; - +// Deprecated. Use std::atomic for new code. // Flag using T atomically. Also accepts void* as T. template class AtomicValue { diff --git a/test-app/runtime/src/main/cpp/v8_inspector/src/base/flags.h b/test-app/runtime/src/main/cpp/v8_inspector/src/base/flags.h index 0a1778f91..b8c3c3407 100644 --- a/test-app/runtime/src/main/cpp/v8_inspector/src/base/flags.h +++ b/test-app/runtime/src/main/cpp/v8_inspector/src/base/flags.h @@ -27,15 +27,15 @@ class Flags final { typedef T flag_type; typedef S mask_type; - Flags() : mask_(0) {} - Flags(flag_type flag) // NOLINT(runtime/explicit) + constexpr Flags() : mask_(0) {} + constexpr Flags(flag_type flag) // NOLINT(runtime/explicit) : mask_(static_cast(flag)) {} - explicit Flags(mask_type mask) : mask_(static_cast(mask)) {} + constexpr explicit Flags(mask_type mask) : mask_(static_cast(mask)) {} - bool operator==(flag_type flag) const { + constexpr bool operator==(flag_type flag) const { return mask_ == static_cast(flag); } - bool operator!=(flag_type flag) const { + constexpr bool operator!=(flag_type flag) const { return mask_ != static_cast(flag); } @@ -52,13 +52,13 @@ class Flags final { return *this; } - Flags operator&(const Flags& flags) const { + constexpr Flags operator&(const Flags& flags) const { return Flags(*this) &= flags; } - Flags operator|(const Flags& flags) const { + constexpr Flags operator|(const Flags& flags) const { return Flags(*this) |= flags; } - Flags operator^(const Flags& flags) const { + constexpr Flags operator^(const Flags& flags) const { return Flags(*this) ^= flags; } @@ -72,24 +72,24 @@ class Flags final { return operator^=(Flags(flag)); } - Flags operator&(flag_type flag) const { + constexpr Flags operator&(flag_type flag) const { return operator&(Flags(flag)); } - Flags operator|(flag_type flag) const { + constexpr Flags operator|(flag_type flag) const { return operator|(Flags(flag)); } - Flags operator^(flag_type flag) const { + constexpr Flags operator^(flag_type flag) const { return operator^(Flags(flag)); } - Flags operator~() const { + constexpr Flags operator~() const { return Flags(~mask_); } - operator mask_type() const { + constexpr operator mask_type() const { return mask_; } - bool operator!() const { + constexpr bool operator!() const { return !mask_; } diff --git a/test-app/runtime/src/main/cpp/v8_inspector/src/base/macros.h b/test-app/runtime/src/main/cpp/v8_inspector/src/base/macros.h index ff0e6aa7e..a2bb5f851 100644 --- a/test-app/runtime/src/main/cpp/v8_inspector/src/base/macros.h +++ b/test-app/runtime/src/main/cpp/v8_inspector/src/base/macros.h @@ -43,7 +43,6 @@ template char (&ArraySizeHelper(const T (&array)[N]))[N]; #endif - // bit_cast is a template function that implements the // equivalent of "*reinterpret_cast(&source)". We need this in // very low-level functions like the protobuf library and fast math @@ -146,24 +145,27 @@ V8_INLINE Dest bit_cast(Source const& source) { void operator delete(void*, size_t) { base::OS::Abort(); } \ void operator delete[](void*, size_t) { base::OS::Abort(); } -// Newly written code should use V8_INLINE and V8_NOINLINE directly. -#define INLINE(declarator) V8_INLINE declarator -#define NO_INLINE(declarator) V8_NOINLINE declarator - -// Define V8_USE_ADDRESS_SANITIZER macros. +// Define V8_USE_ADDRESS_SANITIZER macro. #if defined(__has_feature) #if __has_feature(address_sanitizer) #define V8_USE_ADDRESS_SANITIZER 1 #endif #endif -// Define DISABLE_ASAN macros. +// Define DISABLE_ASAN macro. #ifdef V8_USE_ADDRESS_SANITIZER #define DISABLE_ASAN __attribute__((no_sanitize_address)) #else #define DISABLE_ASAN #endif +// Define V8_USE_MEMORY_SANITIZER macro. +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define V8_USE_MEMORY_SANITIZER 1 +#endif +#endif + // Helper macro to define no_sanitize attributes only with clang. #if defined(__clang__) && defined(__has_attribute) #if __has_attribute(no_sanitize) @@ -271,6 +273,14 @@ struct Use { } // namespace base } // namespace v8 +// implicit_cast(x) triggers an implicit cast from {x} to type {A}. This is +// useful in situations where static_cast(x) would do too much. +// Only use this for cheap-to-copy types, or use move semantics explicitly. +template +V8_INLINE A implicit_cast(A x) { + return x; +} + // Define our own macros for writing 64-bit constants. This is less fragile // than defining __STDC_CONSTANT_MACROS before including , and it // works on compilers that don't have it (like MSVC). @@ -296,6 +306,14 @@ struct Use { #define V8PRIdPTR V8_PTR_PREFIX "d" #define V8PRIuPTR V8_PTR_PREFIX "u" +#ifdef V8_TARGET_ARCH_64_BIT +#define V8_PTR_HEX_DIGITS 12 +#define V8PRIxPTR_FMT "0x%012" V8PRIxPTR +#else +#define V8_PTR_HEX_DIGITS 8 +#define V8PRIxPTR_FMT "0x%08" V8PRIxPTR +#endif + // ptrdiff_t is 't' according to the standard, but MSVC uses 'I'. #if V8_CC_MSVC #define V8PRIxPTRDIFF "Ix" diff --git a/test-app/runtime/src/main/cpp/v8_inspector/src/base/platform/mutex.h b/test-app/runtime/src/main/cpp/v8_inspector/src/base/platform/mutex.h index d82959393..2b63f9abc 100644 --- a/test-app/runtime/src/main/cpp/v8_inspector/src/base/platform/mutex.h +++ b/test-app/runtime/src/main/cpp/v8_inspector/src/base/platform/mutex.h @@ -203,14 +203,22 @@ typedef LazyStaticInstance +// Controls whether a LockGuard always requires a valid Mutex or will just +// ignore it if it's nullptr. +enum class NullBehavior { kRequireNotNull, kIgnoreIfNull }; + +template class LockGuard final { public: explicit LockGuard(Mutex* mutex) : mutex_(mutex) { - mutex_->Lock(); + if (Behavior == NullBehavior::kRequireNotNull || mutex_ != nullptr) { + mutex_->Lock(); + } } ~LockGuard() { - mutex_->Unlock(); + if (mutex_ != nullptr) { + mutex_->Unlock(); + } } private: diff --git a/test-app/runtime/src/main/cpp/v8_inspector/src/base/platform/platform.h b/test-app/runtime/src/main/cpp/v8_inspector/src/base/platform/platform.h index 358e9082b..e4b7eeb7e 100644 --- a/test-app/runtime/src/main/cpp/v8_inspector/src/base/platform/platform.h +++ b/test-app/runtime/src/main/cpp/v8_inspector/src/base/platform/platform.h @@ -48,7 +48,7 @@ namespace base { #define V8_FAST_TLS_SUPPORTED 1 -INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index)); +V8_INLINE intptr_t InternalGetExistingThreadLocal(intptr_t index); inline intptr_t InternalGetExistingThreadLocal(intptr_t index) { const intptr_t kTibInlineTlsOffset = 0xE10; @@ -74,7 +74,7 @@ inline intptr_t InternalGetExistingThreadLocal(intptr_t index) { extern V8_BASE_EXPORT intptr_t kMacTlsBaseOffset; -INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index)); +V8_INLINE intptr_t InternalGetExistingThreadLocal(intptr_t index); inline intptr_t InternalGetExistingThreadLocal(intptr_t index) { intptr_t result; @@ -159,6 +159,7 @@ class V8_BASE_EXPORT OS { // v8::PageAllocator. enum class MemoryPermission { kNoAccess, + kRead, kReadWrite, // TODO(hpayer): Remove this flag. Memory should never be rwx. kReadWriteExecute, diff --git a/test-app/runtime/src/main/cpp/v8_inspector/src/base/template-utils.h b/test-app/runtime/src/main/cpp/v8_inspector/src/base/template-utils.h index 463d341af..7e0c29149 100644 --- a/test-app/runtime/src/main/cpp/v8_inspector/src/base/template-utils.h +++ b/test-app/runtime/src/main/cpp/v8_inspector/src/base/template-utils.h @@ -56,13 +56,6 @@ std::unique_ptr make_unique(Args&& ... args) { return std::unique_ptr(new T(std::forward(args)...)); } -// implicit_cast(x) triggers an implicit cast from {x} to type {A}. This is -// useful in situations where static_cast(x) would do too much. -template -A implicit_cast(A x) { - return x; -} - // Helper to determine how to pass values: Pass scalars and arrays by value, // others by const reference (even if it was a non-const ref before; this is // disallowed by the style guide anyway). diff --git a/test-app/runtime/src/main/cpp/v8_inspector/src/checks.h b/test-app/runtime/src/main/cpp/v8_inspector/src/checks.h index 0d7eed348..8eb10f43d 100644 --- a/test-app/runtime/src/main/cpp/v8_inspector/src/checks.h +++ b/test-app/runtime/src/main/cpp/v8_inspector/src/checks.h @@ -27,9 +27,8 @@ static const bool FLAG_enable_slow_asserts = false; } // namespace internal } // namespace v8 -#define DCHECK_TAG_ALIGNED(address) \ - DCHECK((reinterpret_cast(address) & \ - ::v8::internal::kHeapObjectTagMask) == 0) +#define DCHECK_TAG_ALIGNED(address) \ + DCHECK((address & ::v8::internal::kHeapObjectTagMask) == 0) #define DCHECK_SIZE_TAG_ALIGNED(size) \ DCHECK((size & ::v8::internal::kHeapObjectTagMask) == 0) diff --git a/test-app/runtime/src/main/cpp/v8_inspector/src/conversions.h b/test-app/runtime/src/main/cpp/v8_inspector/src/conversions.h index 5088e5b5c..9a8ee578d 100644 --- a/test-app/runtime/src/main/cpp/v8_inspector/src/conversions.h +++ b/test-app/runtime/src/main/cpp/v8_inspector/src/conversions.h @@ -36,12 +36,13 @@ inline int FastD2IChecked(double x) { return static_cast(x); } - // The fast double-to-(unsigned-)int conversion routine does not guarantee // rounding towards zero. -// The result is unspecified if x is infinite or NaN, or if the rounded +// The result is undefined if x is infinite or NaN, or if the rounded // integer value is outside the range of type int. inline int FastD2I(double x) { + DCHECK(x <= INT_MAX); + DCHECK(x >= INT_MIN); return static_cast(x); } @@ -173,8 +174,9 @@ inline uint32_t NumberToUint32(Object* number); inline int64_t NumberToInt64(Object* number); inline uint64_t PositiveNumberToUint64(Object* number); -double StringToDouble(UnicodeCache* unicode_cache, Handle string, - int flags, double empty_string_val = 0.0); +double StringToDouble(Isolate* isolate, UnicodeCache* unicode_cache, + Handle string, int flags, + double empty_string_val = 0.0); inline bool TryNumberToSize(Object* number, size_t* result); diff --git a/test-app/runtime/src/main/cpp/v8_inspector/src/debug/debug-interface.h b/test-app/runtime/src/main/cpp/v8_inspector/src/debug/debug-interface.h index 717d5737c..71713bf75 100644 --- a/test-app/runtime/src/main/cpp/v8_inspector/src/debug/debug-interface.h +++ b/test-app/runtime/src/main/cpp/v8_inspector/src/debug/debug-interface.h @@ -21,6 +21,7 @@ struct CoverageScript; struct TypeProfileEntry; struct TypeProfileScript; class Coverage; +class PostponeInterruptsScope; class Script; class TypeProfile; } // namespace internal @@ -33,51 +34,13 @@ int GetContextId(Local context); void SetInspector(Isolate* isolate, v8_inspector::V8Inspector*); v8_inspector::V8Inspector* GetInspector(Isolate* isolate); -/** - * Debugger is running in its own context which is entered while debugger - * messages are being dispatched. This is an explicit getter for this - * debugger context. Note that the content of the debugger context is subject - * to change. The Context exists only when the debugger is active, i.e. at - * least one DebugEventListener or MessageHandler is set. - */ -Local GetDebugContext(Isolate* isolate); - -/** - * Run a JavaScript function in the debugger. - * \param fun the function to call - * \param data passed as second argument to the function - * With this call the debugger is entered and the function specified is called - * with the execution state as the first argument. This makes it possible to - * get access to information otherwise not available during normal JavaScript - * execution e.g. details on stack frames. Receiver of the function call will - * be the debugger context global object, however this is a subject to change. - * The following example shows a JavaScript function which when passed to - * v8::Debug::Call will return the current line of JavaScript execution. - * - * \code - * function frame_source_line(exec_state) { - * return exec_state.frame(0).sourceLine(); - * } - * \endcode - */ -// TODO(dcarney): data arg should be a MaybeLocal -MaybeLocal Call(Local context, v8::Local fun, - Local data = Local()); - -/** - * Enable/disable LiveEdit functionality for the given Isolate - * (default Isolate if not provided). V8 will abort if LiveEdit is - * unexpectedly used. LiveEdit is enabled by default. - */ -V8_EXPORT_PRIVATE void SetLiveEditEnabled(Isolate* isolate, bool enable); - -// Schedule a debugger break to happen when JavaScript code is run -// in the given isolate. -void DebugBreak(Isolate* isolate); +// Schedule a debugger break to happen when function is called inside given +// isolate. +void SetBreakOnNextFunctionCall(Isolate* isolate); // Remove scheduled debugger break in given isolate if it has not // happened yet. -void CancelDebugBreak(Isolate* isolate); +void ClearBreakOnNextFunctionCall(Isolate* isolate); /** * Returns array of internal properties specific to the value type. Result has @@ -116,18 +79,28 @@ void BreakRightNow(Isolate* isolate); bool AllFramesOnStackAreBlackboxed(Isolate* isolate); -/** - * Out-of-memory callback function. - * The function is invoked when the heap size is close to the hard limit. - * - * \param data the parameter provided during callback installation. - */ -typedef void (*OutOfMemoryCallback)(void* data); +class Script; -V8_DEPRECATED("Use v8::Isolate::AddNearHeapLimitCallback", - void SetOutOfMemoryCallback(Isolate* isolate, - OutOfMemoryCallback callback, - void* data)); +struct LiveEditResult { + enum Status { + OK, + COMPILE_ERROR, + BLOCKED_BY_RUNNING_GENERATOR, + BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME, + BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME, + BLOCKED_BY_ACTIVE_FUNCTION, + BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME, + FRAME_RESTART_IS_NOT_SUPPORTED + }; + Status status = OK; + bool stack_changed = false; + // Available only for OK. + v8::Local script; + // Fields below are available only for COMPILE_ERROR. + v8::Local message; + int line_number = -1; + int column_number = -1; +}; /** * Native wrapper around v8::internal::Script object. @@ -157,7 +130,7 @@ class V8_EXPORT_PRIVATE Script { int GetSourceOffset(const debug::Location& location) const; v8::debug::Location GetSourceLocation(int offset) const; bool SetScriptSource(v8::Local newSource, bool preview, - bool* stack_changed) const; + LiveEditResult* result) const; bool SetBreakpoint(v8::Local condition, debug::Location* location, BreakpointId* id) const; }; @@ -184,17 +157,14 @@ MaybeLocal CompileInspectorScript(Isolate* isolate, class DebugDelegate { public: virtual ~DebugDelegate() {} - virtual void PromiseEventOccurred(debug::PromiseDebugActionType type, int id, - bool is_blackboxed) {} virtual void ScriptCompiled(v8::Local