Commit Graph
26 Commits
Author SHA1 Message Date
Neil Dhar cd5a8c48c5 Only intercept JSIExceptions when constructing JSError
Summary:
Constructing a `JSError` currently catches all exceptions that occur,
regardless of their type, and embeds the information from them in the
newly created `JSError`. This means that the type of exceptions can be
silently changed.

This results in a bug if Hermes is built with
`HERMESVM_EXCEPTION_ON_OOM` enabled. The OOM exception will get
converted to a `JSError`, which in turn can get converted into a
regular JS exception. The regular JS exception can then be caught by JS
and ignored. This leads to the VM continuing to execute in a bad
state.

I considered three ways to fix this:
1. Add a new type of exception to JSI that is intentionally meant to be
ignored, and the Hermes OOM exception then subclasses it.
2. Propagate all exceptions that happen when constructing `JSError`.
3. Propagate all exceptions except `JSIException`s when constructing
`JSError`.

The first is technically the most surgical, but it adds complexity to
JSI, and will require some extra machinery to implement since we
wouldn't be able to throw it directly from inside the VM. I'm also not
comfortable with the idea of JSI suppressing exceptions that are
completely unrelated to JSI.

The second is the simplest, and seems to match what JS would do if
`throw new Error()` itself threw, but there is some possibility that it
is a change in behaviour for existing code.

So the third approach, which is implemented in this diff, tries to
compromise between the two. Hermes can only ever throw `JSIException`s
from regular JS operations, so there should be no change for existing
code (except code that uses exceptions on OOM, which is what we're
trying to fix). Any other exception gets passed through to the caller.

Changelog:
[Internal][Fixed] - Fixed handling of Hermes OOM exceptions in JSI.

Reviewed By: jpporto

Differential Revision: D41831616

fbshipit-source-id: 42e0dde1c4acc016ab19533941c58fc1797ba1c2
2023-01-22 00:25:49 -08:00
Neil Dhar 3bae268782 Add external ArrayBuffers to JSI (#793)
Summary:
X-link: https://github.com/facebook/hermes/pull/793

Add a JSI API for constructing `ArrayBuffer`s from a user provided
`jsi::MutableBuffer`.

Changelog: [General][Added] Added ability to construct ArrayBuffers from existing memory buffers.

Reviewed By: jpporto

Differential Revision: D37744467

fbshipit-source-id: 9d9ece00d1dbde341846c45fa30c935b5fa81e9a
2022-08-23 08:35:34 -07:00
John Porto a21a1f845b Add methods for creating and interacting with BigInt
Summary:
This change adds the following methods to jsi::BigInt

  * [static] fromInt64(value): creates a jsi::BigInt from a signed 64-bit value
  * [static] fromUint64(value): creates a jsi::BigInt from an unsigned 64-bit value
  * [static] strictEquals(a, b): return a === b, a and b are BigInts
  * asInt64(): truncates the BigInt to a single signed 64-bit integer; throws a JSIException if the truncation is lossy.
  * getInt64(): truncates the BigInt to a single signed 64-bit integer
  * isInt64(): returns true if the BigInt can be truncated losslessly to an int64_t
  * asUint64(): truncates the BigInt to a single unsigned 64-bit integer; throws a JSIException if the truncation is lossy.
  * getUint64(): truncates the BigInt to a single unsigned 64-bit integer
  * isUint64(): returns true if the BigInt can be truncated losslessly to an uint64_t
  * toString(radix): converts the BigInt to a string representing the number in the given radix.

 A lossy truncation is one that yields a result from which the BigInt cannot be reconstructed from, i.e.,
* BigInt::fromInt64(b.toInt64()) !== b
* BigInt::fromUint64(b.toUint64()) !== b

Changelog: [Internal]

Reviewed By: kodafb

Differential Revision: D37909139

fbshipit-source-id: 172848024f8367aed73cc602f38cde22f03cac8f
2022-07-29 07:55:57 -07:00
Daniel Andersson 6179233965 Add API for setting/getting native state
Summary:
Add API for setting/getting native state.

When present, the internal NativeState property of an object always stores a NativeState with a pointer to a heap-allocated shared_ptr + a finalizer that simply `delete`s it.

Changelog:
[Internal][Added] - JSI API for setting/getting native state on a JS object

Reviewed By: jpporto

Differential Revision: D36499239

fbshipit-source-id: a1ff1905811db1aac99ece3f928b81d0abfb342b
2022-07-18 15:29:50 -07:00
John Porto 11bae63bb1 Add BigInt skeleton
Summary:
Adds a jsi::BigInt skeleton.

Changelog:
[General][Added] jsi::BigInt

Reviewed By: kodafb

Differential Revision: D35706101

fbshipit-source-id: 435b108050279ff30953b3e209cdc2f0ff84f40b
2022-07-08 11:40:33 -07:00
Neil Dhar 0035cc9292 Fix throwing exceptions from asHostObject
Summary:
The current implementation of `throwJSError` places it in jsi.cpp, but
does not actually export it. This means that when JSI is being provided
by a dynamic library, `detail::throwJSError` will not be available.

To fix this, move the definition of `throwJSError` into jsi-inl.h,
similar to all of the other functions in the `detail` namespace. This
uses a roundabout implementation of `throwJSError` in order to avoid
directly using `throw`, which would fail to compile when exceptions are
turned off.

Changelog: [Internal]

Reviewed By: jpporto

Differential Revision: D36873154

fbshipit-source-id: bbea48e0d4d5fd65d67a029ba12e183128b96322
2022-06-03 15:04:46 -07:00
Scott Kyle 603620b739 Add asBool() method
Summary:
Changelog:
[General][Added] - Add asBool() method to JSI

Reviewed By: mhorowitz

Differential Revision: D34630901

fbshipit-source-id: 3007784618fcc0f7828eee42de5cbf2bd71258c5
2022-03-04 08:02:17 -08:00
Neil Dhar 5b66bb90c6 Add missing symbol handling in kindToString
Summary: Changelog: [Internal]

Reviewed By: kodafb

Differential Revision: D34062869

fbshipit-source-id: 08fed59d62b0d0a46e0868874a89b125731a44e5
2022-02-08 15:18:15 -08:00
Andres Suarez 8bd3edec88 Update copyright headers from Facebook to Meta
Reviewed By: aaronabramov

Differential Revision: D33367752

fbshipit-source-id: 4ce94d184485e5ee0a62cf67ad2d3ba16e285c8f
2021-12-30 15:11:21 -08:00
Riley Dulin a9bae13d07 Add sampling heap profiler APIs to JSI
Summary:
The sampling heap profiler will need to be enable-able by the
inspector, and the previous snapshot/profiling APIs are all
defined on `jsi::instrumentation`.

Follow their lead and define the new sampling heap profiler APIs on
`jsi::instrumentation` as well, and implement it for Hermes.

Changelog: [Internal]

Reviewed By: neildhar

Differential Revision: D26835152

fbshipit-source-id: 4625be3214297489e04a4ceea8a22622d14299c4
2021-03-18 10:40:41 -07:00
Riley Dulin d8b0e9d9ab Add HeapProfiler.lastSeenObjectId and HeapProfiler.heapStatsUpdate to inspector
Summary:
When taking a heap timeline, Hermes wasn't showing any data until the timeline
was written to disk and then reloaded.

Turns out we were missing support for two events:
* `HeapProfiler.lastSeenObjectId`: This event reports the most recently
allocated object ID. Used to know when objects were allocated in the
timeline.
* `HeapProfiler.heapStatsUpdate`: Report how many objects and bytes
exist for a "time fragment", represented by a fragment index. Later updates
to the same index can decrease the amount of live memory, which show up
as grey spikes instead of blue spikes

Previously, we only supported these by writing out to a file, and they didn't work
with a "live" profiling view. To fix this, I changed the periodic sampling thread
to instead be a periodic flush of a sample every few allocations. The performance
impact is tucked away only when profiling is turned on, and it's very non-invasive to
the rest of the GC. The flush calls a callback with the relevant information if the
inspector is on, and the inspector sends a message back to the browser.

Changelog: [Internal] Fix for Hermes heap timeline profiling

Reviewed By: neildhar

Differential Revision: D23993363

fbshipit-source-id: 8e0b571130cbb7e839dfb009b04f584f5179085d
2020-10-10 13:26:13 -07:00
Riley Dulin 22804a6144 Add cause to jsi::instrumentation::collectGarbage
Summary:
Continuing the adding of a "cause" field for logging to GCs.
This allows embedders of Hermes (such as React Native) to specify
the cause of a call to `collectGarbage`.

Notably, this allows Hermes to know when a GC is triggered by a memory warning.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D23742099

fbshipit-source-id: 99453e632328c00045b92a72f789d41c898dc518
2020-09-18 10:36:19 -07:00
Marc Horowitz 9baf6f2140 Handle stack overflow in JSError construction gracefully
Summary:
JSError creation can lead to further errors.  Make sure these cases
are handled and don't cause weird crashes or other issues.

This solution has a few parts:
 * include a ScopedNativeDepthTracker in checkStatus
 * If an exception object message or stack property is already a String, don't
   call JS String ctor on it
 * Verify that a jsi::Value is a String before calling getString on it.
 * Add more tests for JSError construction

Changelog: [Internal]

Reviewed By: dulinriley

Differential Revision: D21851645

fbshipit-source-id: 2d10da0e741ad4ede93cd806320f68ad512e5138
2020-06-03 18:14:18 -07:00
Pieter De Baets e566c7ec7b Add virtual destructor to JSError
Summary:
We consume Hermes through multiple .so's, which means we have multiple (weak) typeinfo definitions of facebook::jsi::JSError. Previously we were using gnustl, which would strcmp typeinfo to decide whether a certain exception handler applies, which meant this didn't cause any major issues. However since this is deprecated, we recently switched to libc++, which does not have this by behaviour (or it does, but behind a flag I'm not sure how to enable). This causes any JS exceptions to fall through from our exception handlers and fatal the app.

This problem is actually documented in the common Android NDK problems page: https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md#rtti_exceptions-not-working-across-library-boundaries

The suggested solution is to ensure that any exception types have a key function defined (a non-pure, out-of-line virtual function). The simplest one to add is a virtual destructor. This makes the object file that holds the implementation of the destructor export a non-weak typeinfo definition which will at load time override the other weak versions.

I'm not sure why we're the first to hit this. RN's JSIExecutor doesn't explicitly reference JSError which probably helps (https://github.com/facebook/react-native/blob/master/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp#L256-L258) and they also don't use unguarded callbacks like we do.

Changelog: [Internal]

Reviewed By: mhorowitz

Differential Revision: D21426524

fbshipit-source-id: 474284ada1ca2810045dc4402c420879447f9308
2020-05-07 04:15:14 -07:00
Jacob Bower ed3054927c Plumb through memory allocation profiler feature to Chrome Inspector
Summary: Changelog: Make allocation profiler feature of Chome Inspector work

Reviewed By: dulinriley

Differential Revision: D20383003

fbshipit-source-id: 8a10c310d5a639a6644763adb53f2f0017057587
2020-03-31 11:02:41 -07:00
David Detlefs 14ac53363e Make synth trace write incrementally to a file.
Summary:
If we're using synth traces in production, we probably don't want to accumulate the trace in memory, and write it to a file in one big step when an error happens.  Rather, we'd like to write the trace incrementally, to a file: file system space is less scarse than memory, and doing it incrementally means less to do in the error handler.

This diff is the first step towards writing the synth trace incrementally.  The most difficult aspect of this is that in the existing code, on Android, the trace is written in the handler of an Intent.  Java-level operations on the Intent yielded a temporary filename under the application (so if the application is uninstalled, these temporary files are deleted).  We must do something similar, but choose the filename within native code, on construction of the SynthTrace object.  We copy what profiling does for this: assume the tmp dir is /data/data/<app>, where <app> can be found from reading /proc/self/cmdLine.

The SynthTrace constructor now takes a new argument: a unique_pointer to a stream.  If null, no trace file is written, and the SynthTrace just accumulates records in memory.  (This functionality is used during trace replay.) . If non-null, the trace is written to that stream.

The "write{BridgeTraffic}Trace..." methods become "flushAndDisable{BridgeTrafficTrace}" methods.

This diff is the first step towards incremental traces: the trace is still written at the end, but we've arranged that the place to write it is available at construction of the SynthTrace object.  Later diffs will move recording of static things (e.g., the RuntimeConfig) into the ctor, then actually make us write the trace to the file incrementally.

For ReactNative:

Changelog: [Internal]

Reviewed By: haozhun, dulinriley

Differential Revision: D19471297

fbshipit-source-id: c1de4d2d9f44a87c7ff6fea38a1ce67de593940c
2020-02-13 13:01:06 -08:00
Riley Dulin 9b7958c2f2 Have heap snapshots throw std::system_error instead of return a bool
Summary:
Instead of returning a `bool` which gives no information about the cause of the error,
return `void` and throw when there's some error.

Another alternative is returning `std::error_code`, but that's less flexible than throwing, and
this API already supports throwing.

Changelog: [Internal]

Reviewed By: jbower-fb

Differential Revision: D19170033

fbshipit-source-id: 870cd996a1a53c94524455f31765c1da99f57a1d
2020-02-12 17:11:46 -08:00
Marc Horowitz a195447539 Handle errors building JSErrors better
Summary:
If building a JSError causes a JSError, this would lead to infinite recursion.  This changes the error handling path so the problem is visible to JS.  There's also a few related cleanups included, and a new test case.

Changelog: [General] [Fixed] - If Error global is not callable when building an error, jsi will throw a JS exception back to JS code. #158

Reviewed By: tmikov, dulinriley

Differential Revision: D18796269

fbshipit-source-id: 57a45d144fa2ea5e78d18c27d3130611737dda96
2019-12-19 21:33:18 -08:00
Riley Dulin f91a21b2c0 Remove compact parameter from heap snapshots
Summary:
This parameter used to be useful for a custom format hermes was developing,
but since Hermes now outputs the Chrome format it isn't useful.
Chrome actually disallows prettified JSON, and requires a special version that is faster to parse.
Therefore, `compact` was the only supported mode.

Changelog: [Internal] Remove compact parameter from `createSnapshotToFile`

Reviewed By: willholen

Differential Revision: D17726742

fbshipit-source-id: 6f39af9046dff2f3b4fba822312a9a89c939ed89
2019-10-31 14:48:01 -07:00
Andres Suarez d8560a838b Tidy up license headers [3/n]
Summary: Changelog: [General] [Fixed] - License header cleanup

Differential Revision: D18033336

fbshipit-source-id: 0334bfa2d61314de6ee9e7302205c08574abc0d9
2019-10-21 10:43:00 -07:00
Daniel Andersson 9e7e178a2d Make it possible for a Runtime to provide its own JSON parsing
Summary: Make it possible for a Runtime implementation to provide its own JSON parsing, by making the method on Value call through Runtime, which now has the default implementation.

Reviewed By: tmikov

Differential Revision: D17637395

fbshipit-source-id: b8997f7d1721a7790326417f3abfa86c875923c9
2019-09-29 18:55:53 -07:00
Riley Dulin 0c7defcf64 Remove jsi::Value return from jsi::Instrumentation::getHeapInfo
Summary:
`getHeapInfo` was creating and return a `jsi::Object`. This object was not being traced
when API tracing was turned on.
This resulted in a bug in synth traces, an object was being acted upon without its creation source
being logged.
In order to prevent this, change the API of `getHeapInfo` to no longer return any objects, or modify other heap
contents.

This is preferable to having `TracingRuntime` attempt to mimic the operations of two different implementations.

## Changelog:

[Internal] [Changed] - Changed `jsi::Instrumentation::getHeapInfo` to use a `std::unordered_map`

Reviewed By: mhorowitz

Differential Revision: D17273235

fbshipit-source-id: f69860dcc524c2cf501746a41dbac20b4db8c456
2019-09-13 18:47:36 -07:00
Ashok Menon 14686259d9 Create Snapshot From Stream
Summary:
Adding an instrumentation endpoint that allows us to write a snapshot out to an
arbitrary output stream.  This is in addition to `createSnapshotFromFile`.  I
reserve the right to replace the latter with the former in a later diff.

This is necessary to allow snapshots to be requested over the chrome debugger
protocol.  The protocol sends the snapshot over the wire in chunks so we need
to be able to use an output stream that can do the chunking.

Because LLVM types are not available at the JSI layer, we accept a
`std::ostream` reference which we wrap with `llvm::raw_os_ostream` within
Hermes.  We should not incur the static initializer cost (or other code bloat)
of using ostreams as a result.

Reviewed By: cwdick

Differential Revision: D16016319

fbshipit-source-id: 2d0b4848fd5cbe9ddee371d856cd8eb19dd80396
2019-06-28 06:15:33 -07:00
Rain ⁣ 14f249178e standardize C-like MIT copyright headers throughout fbsource
Summary:
`/*` is the standard throughout open source code. For example, Firefox uses single /*: https://hg.mozilla.org/mozilla-central/file/21d22b2f541258d3d1cf96c7ba5ad73e96e616b5/gfx/ipc/CompositorWidgetVsyncObserver.cpp#l3

In addition, Rust considers `/**` to be a doc comment (similar to Javadoc) and having such a comment at the beginning of the file causes `rustc` to barf.

Note that some JavaScript tooling requires `/**`. This is OK since JavaScript files were not covered by the linter in the first place, but it would be good to have that tooling fixed too.

Reviewed By: zertosh

Differential Revision: D15640366

fbshipit-source-id: b4ed4599071516364d6109720750d6a43304c089
2019-06-06 19:40:32 -07:00
Will Holen 5e5439a921 Update JSI from upstream
Summary: This change synchronizes the JSI API with its upstream, aiming to make this easier to automate in the future.

Reviewed By: mhorowitz

Differential Revision: D14783311

fbshipit-source-id: c180d0f728afbeb87a3e8e7331a39c06e73b907e
2019-04-09 11:44:32 -07:00
Will Holen 094f221a0c Move JSI source files into a separate directory
Summary: This will simplify updating the JSI API from upstream in the future.

Reviewed By: mhorowitz

Differential Revision: D14762674

fbshipit-source-id: fa4a86f08425943e301da4ef3df9893ebaa1493e
2019-04-09 11:44:32 -07:00