Repository: nodejs/node
Pull request: doc: avoid suggesting testing fast api with intense loop

Update the doc to suggest testing a fast api with V8 `%PrepareFunctionForOptimization` native syntax.

Also, make this a requirement.

Refs: https://github.com/nodejs/node/pull/59055

Changed files:
filename: doc/contributing/adding-v8-fast-api.md
patch: @@ -26,15 +26,8 @@ for example, they may not trigger garbage collection.
   in a snapshot (either the built-in or a user-land one). Please refer to the
   [binding functions documentation](../../src/README.md#binding-functions) for more
   information.
-* To test fast APIs, make sure to run the tests in a loop with a decent
-  iterations count to trigger relevant optimizations that prefer the fast API
-  over the slow one.
-* In debug mode (`--debug` or `--debug-node` flags), the fast API calls can be
-  tracked using the `TRACK_V8_FAST_API_CALL("key")` macro. This can be used to
-  count how many times fast paths are taken during tests. The key is a global
-  identifier and should be unique across the codebase.
-  Use `"binding_name.function_name"` or `"binding_name.function_name.suffix"` to
-  ensure uniqueness.
+* Fast API functions must be tested following the example in
+  [Test with Fast API path](#test-with-fast-api-path).
 * The fast callback must be idempotent up to the point where error and fallback
   conditions are checked, because otherwise executing the slow callback might
   produce visible side effects twice.
@@ -175,40 +168,47 @@ A typical function that communicates between JavaScript and C++ is as follows.
                                                       v8::FastApiCallbackOptions& options);
   ```
 
-* In the unit tests:
-
-  Since the fast API function uses `TRACK_V8_FAST_API_CALL`, we can ensure that
-  the fast paths are taken and test them by writing tests that force
-  V8 optimizations and check the counters.
-
-  ```js
-  // Flags: --expose-internals --no-warnings --allow-natives-syntax
-  'use strict';
-  const common = require('../common');
-
-  const { internalBinding } = require('internal/test/binding');
-  // We could also require a function that uses the internal binding internally.
-  const { divide } = internalBinding('custom_namespace');
-
-  // The function that will be optimized. It has to be a function written in
-  // JavaScript. Since `divide` comes from the C++ side, we need to wrap it.
-  function testFastPath(a, b) {
-    return divide(a, b);
-  }
-
-  eval('%PrepareFunctionForOptimization(testFastPath)');
-  // This call will let V8 know about the argument types that the function expects.
-  assert.strictEqual(testFastPath(6, 3), 2);
-
-  eval('%OptimizeFunctionOnNextCall(testFastPath)');
-  assert.strictEqual(testFastPath(8, 2), 4);
-  assert.throws(() => testFastPath(1, 0), {
-    code: 'ERR_INVALID_STATE',
-  });
-
-  if (common.isDebug) {
-    const { getV8FastApiCallCount } = internalBinding('debug');
-    assert.strictEqual(getV8FastApiCallCount('custom_namespace.divide.ok'), 1);
-    assert.strictEqual(getV8FastApiCallCount('custom_namespace.divide.error'), 1);
-  }
-  ```
+### Test with Fast API path
+
+In debug mode (`./configure --debug` or `./configure --debug-node` flags), the
+fast API calls can be tracked using the `TRACK_V8_FAST_API_CALL("key")` macro.
+This can be used to count how many times fast paths are taken during tests. The
+key is a global identifier and should be unique across the codebase.
+Use `"binding_name.function_name"` or `"binding_name.function_name.suffix"` to
+ensure uniqueness.
+
+In the unit tests, since the fast API function uses `TRACK_V8_FAST_API_CALL`,
+we can ensure that the fast paths are taken and test them by writing tests that
+force V8 optimizations and check the counters.
+
+```js
+// Flags: --expose-internals --no-warnings --allow-natives-syntax
+'use strict';
+const common = require('../common');
+
+const { internalBinding } = require('internal/test/binding');
+// We could also require a function that uses the internal binding internally.
+const { divide } = internalBinding('custom_namespace');
+
+// The function that will be optimized. It has to be a function written in
+// JavaScript. Since `divide` comes from the C++ side, we need to wrap it.
+function testFastPath(a, b) {
+  return divide(a, b);
+}
+
+eval('%PrepareFunctionForOptimization(testFastPath)');
+// This call will let V8 know about the argument types that the function expects.
+assert.strictEqual(testFastPath(6, 3), 2);
+
+eval('%OptimizeFunctionOnNextCall(testFastPath)');
+assert.strictEqual(testFastPath(8, 2), 4);
+assert.throws(() => testFastPath(1, 0), {
+  code: 'ERR_INVALID_STATE',
+});
+
+if (common.isDebug) {
+  const { getV8FastApiCallCount } = internalBinding('debug');
+  assert.strictEqual(getV8FastApiCallCount('custom_namespace.divide.ok'), 1);
+  assert.strictEqual(getV8FastApiCallCount('custom_namespace.divide.error'), 1);
+}
+```