- Cleanup "tsCompilerOnMessage" by factoring out separate methods for each
request type:
* "compile"
* "runtimeCompile"
* "runtimeTranspile"
- Simplify control flow of compiler workers by a) no longer calling "close()" in worker runtime after a
single message; b) explicitly shutting down worker from host after a single message
Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
Rewrite "testPerm" helper function used for testing of internal
runtime code. It's been renamed to "unitTest" and provides API that
is extensible in the future by accepting optional "UnitTestOptions"
argument. "test" helper was also removed and replaced by
overloaded version of "unitTest" that takes only function argument.
"UnitTestOptions" currently supports "perms" and "skip"
options, where former works exactly as first argument to "testPerm"
did, while the latter allows to conditionally skip tests.
* add "assertOps" test assertion which makes sure test case
is not "leaking" ops - ie. after test finishes there are no
pending async ops
* apply "assertOps" to all tests in "cli/js/"
* fix numerous tests leaking ops
* document problem with edge case in "clearInterval"
and "clearTimeout" implementation where they
may leak async ops
* move "cli/js/worker_test.ts" to "cli/tests/worker_test.ts" and
run as integration test; workers leak ops because of missing
"terminate" implementation
Fixes #4602
We turned off `allowJs` by default, to keep the compiler from grabbing
a bunch of files that it wouldn't actually do anything useful with. On
the other hand, this caused problems with bundles, where the compiler
needs to gather all the dependencies, including JavaScript ones. This
fixes this so that when we are bundling, we analyse JavaScript imports
in the compiler.
* Rename MkdirOption interface to MkdirOptions
It was hard to remember which Options interfaces were spelled in the
singular and which in the plural (and anyway this one contained two
options).
Also added MkdirOptions to cli/js/deno.ts. All the analogous interfaces
were exported there.
* Rename RemoveOption interface to RemoveOptions
This was the last remaining Option interface spelled in the singular.
Easier to remember if they're all Option**s**; plus we may want to add extra
options here later.
Rewrite "normalize_path()" to remove all intermediate components from the path, ie. "./" and "../". It's very similar in functionality to fs::canonicalize(), however "normalize_path() doesn't resolve symlinks.
Previously, bundles always utilised top level await, even if the bundled
modules didn't require top level await. Now, analysis of the bundle is
done and if none of the bundled modules are asynchronously executed,
then the bundle as a whole will be synchronously executed.
Fixes #4055
Fixes #4123
- Added `ServerRequest.finalize()`: consuming all unread body stream and trailers.
- This is cleanup method for reading next request from same keep-alive connection.
- Needed when handler didn't consume all body and trailers even after responding.
- refactor: `ServerRequest._bodyStream()`, `ServerRequestBody` are removed.
- Now using `bodyReader()` and `chunkedBodyReader()` instead.
- fix: Trailers should only be read `transfer-encoding` is `chunked` and `trailer` header is set and its value is valid.
- fix: use `Headers.append()` on reading trailers.
- fix: delete `trailer` field from headers after reading trailers.
- reorg: Several functions related to IO are moved into `http/io.ts`
This PR introduces the mutex guard for the test cases which depends on the
permission prompt mocking utility. permission_request test cases depend on
the mocked (dummy) value of the permission_prompt result. The value is stored
at static STUB_PROMPT_VALUE: AtomicBool and these test cases share this
value. So we should lock at the start of these test cases.
Before this change cargo test permission failed 6 times out of 20. After this
change, 0 times out of 20 (on my mac).
To better reflect changes in error types in JS from #3662 this PR changes
default error type used in ops from "ErrBox" to "OpError".
"OpError" is a type that can be sent over to JSON; it has all
information needed to construct error in JavaScript. That
made "GetErrorKind" trait useless and so it was removed altogether.
To provide compatibility with previous use of "ErrBox" an implementation of
"From<ErrBox> for OpError" was added, however, it is an escape hatch and
ops implementors should strive to use "OpError" directly.
This PR fixes an issue where we recursively analysed imports on plain JS files
in the compiler irrespective of "checkJs" being true. This caused problems
where when analysing the imports of those files, we would mistake some
import like structures (AMD/CommonJS) as dependencies and try to resolve
the "modules" even though the compiler would not actually look at those files.
Fixes #4031
When a bundle contains a single module, we were incorrectly determining
the module name, resulting in a non-functional bundle. This PR corrects
that determination.
Example:
$ python2 -c 'open("\x80\x7F", "w")'
$ deno eval 'Deno.readDirSync(".")'
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', cli/ops/fs.rs:373:16
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 5
Aborted (core dumped)
Before this commit they made deno panic, now they are silently skipped.
Not ideal but arguably better than panicking.
No test because what characters are and aren't allowed in filenames is
highly file system-dependent.
Closes #3950
Moves to using a minimal System loader for bundles generated by Deno.
TypeScript in 3.8 will be able to output TLA for modules, and the loader
is written to take advantage of that as soon as we update Deno to TS
3.8.
System also allows us to support `import.meta` and provide more ESM
aligned assignment of exports, as well as there is better handling of
circular imports.
The loader is also very terse versus to try to save overhead.
Also, fixed an issue where abstract classes were not being re-exported.
Fixes #2553
Fixes #3559
Fixes #3751
Fixes #3825
Refs #3301
* rewrite test runner in Rust
* migrate "test" and "runTests" functions from std to "Deno" namespace
* use "Deno.test()" to run internal JS unit tests
* remove std downloads for Deno subcommands
* Use PathBuf for DenoSubcommand::Bundle's out_file
* Use PathBuf for DenoSubcommand::Format's files
* Use PathBuf for DenoSubcommand::Install's dir
* Use PathBuf for read/write whitelists
* establish basic event loop for workers
* make "self.close()" inside worker
* remove "runWorkerMessageLoop() - instead manually call global function
in Rust when message arrives. This is done in preparation for structured clone
* refactor "WorkerChannel" and use distinct structs for internal
and external channels; "WorkerChannelsInternal" and "WorkerHandle"
* move "State.worker_channels_internal" to "Worker.internal_channels"
* add "WorkerEvent" enum for child->host communication;
currently "Message(Buf)" and "Error(ErrBox)" variants are supported
* add tests for nested workers
* add tests for worker throwing error on startup
In denoland/deno#2335 a conditional was added to make sure
toAsyncIterator didn't skip chunks because the reader returned data and
EOF in a single call, fixing #2330.
Later, in denoland/deno#2591, the `Reader` interface changed to
`Promise<number | EOF>`. Since the reader no longer returns data and EOF
in a single call, this conditional is not necessary. We can just return
`{ done: true }` when we get `EOF`.
Co-authored-by: Arun Srinivasan <rulfzid@gmail.com>
Co-authored-by: Arun Srinivasan <rulfzid@gmail.com>
- Exports diagnostic items from `diagnostics.ts` which are missing at
runtime.
- Returns an array of diagnostics, instead of an object with a property
of `items`. This is because of the way Rust deals with certain
structures, and shouldn't be exposed in the APIs.
This change simplifies how we execute V8. Previously V8 Isolates jumped
around threads every time they were woken up. This was overly complex and
potentially hurting performance in a myriad ways. Now isolates run on
their own dedicated thread and never move.
- blocking_json spawns a thread and does not use a thread pool
- op_host_poll_worker and op_host_resume_worker are non-operational
- removes Worker::get_message and Worker::post_message
- ThreadSafeState::workers table contains WorkerChannel entries instead
of actual Worker instances.
- MainWorker and CompilerWorker are no longer Futures.
- The multi-threaded version of deno_core_http_bench was removed.
- AyncOps no longer need to be Send + Sync
This PR is very large and several tests were disabled to speed
integration:
- installer_test_local_module_run
- installer_test_remote_module_run
- _015_duplicate_parallel_import
- _026_workers
For some reason, the unit tests for Deno.remove() were not being imported to
unit_tests.ts and, consequently, not being executed. Thus, I imported them,
refactored some existent ones and wrote new ones for the symlink removal case.
Since the creation of a symlink is not implemented for Windows yet, assertions
that consider this state were added when the tests are executed in this OS.
This flag was added to evaluate performance relative to tokio's threaded
runtime. Although it's faster in the HTTP benchmark, it's clear the runtime
is not the only perf problem.
Removing this flag will simplify further refactors, in particular
adopting the #[tokio::main] macro. This will be done in a follow up.
Ultimately we expect to move to the current thread runtime with Isolates
pinned to specific threads, but that will be a much larger refactor. The
--current-thread just complicates that effort.
Before:
```
▶ target/debug/deno https://deno.land/std/examples/echo_server.ts
error: Uncaught PermissionDenied: run again with the --allow-net flag
► $deno$/dispatch_json.ts:40:11
at DenoError ($deno$/errors.ts:20:5)
at unwrapResponse ($deno$/dispatch_json.ts:40:11)
at sendSync ($deno$/dispatch_json.ts:67:10)
at listen ($deno$/net.ts:170:15)
at https://deno.land/std/examples/echo_server.ts:4:23
```
```
▶ target/debug/deno --allow-read=/usr https://deno.land/std/examples/cat.ts /etc/passwd
error: Uncaught PermissionDenied: run again with the --allow-read flag
► $deno$/dispatch_json.ts:40:11
at DenoError ($deno$/errors.ts:20:5)
at unwrapResponse ($deno$/dispatch_json.ts:40:11)
at sendAsync ($deno$/dispatch_json.ts:91:10)
```
After:
```
▶ target/debug/deno https://deno.land/std/examples/echo_server.ts
error: Uncaught PermissionDenied: network access to "0.0.0.0:8080", run again with the --allow-net flag
► $deno$/dispatch_json.ts:40:11
at DenoError ($deno$/errors.ts:20:5)
at unwrapResponse ($deno$/dispatch_json.ts:40:11)
at sendSync ($deno$/dispatch_json.ts:67:10)
at listen ($deno$/net.ts:170:15)
at https://deno.land/std/examples/echo_server.ts:4:23
```
```
▶ target/debug/deno --allow-read=/usr https://deno.land/std/examples/cat.ts /etc/passwd
error: Uncaught PermissionDenied: read access to "/etc/passwd", run again with the --allow-read flag
► $deno$/dispatch_json.ts:40:11
at DenoError ($deno$/errors.ts:20:5)
at unwrapResponse ($deno$/dispatch_json.ts:40:11)
at sendAsync ($deno$/dispatch_json.ts:91:10)
```
* move is_dyn_import argument from Loader::resolve to Loader::load - it was always kind of strange that resolve() checks permissions.
* change argument type from &str to &ModuleSpecifier where applicable
Ref #3712. This change allowed the deno_typescript crate to reference
cli/js/lib.deno_runtime.d.ts which breaks "cargo package". We intend to
reintroduce a revised version of this patch later once "cargo
package" is working and tested.
This reverts commit 737ab94ea1.
* split ops/worker.rs into ops/worker_host.rs and ops/web_worker.rs
* refactor js/workers.ts and factor out js/worker_main.ts - entry point for WebWorker runtime
* BREAKING CHANGE: remove support for blob: URL in Worker
* BREAKING CHANGE: remove Deno namespace support and noDenoNamespace option in Worker constructor
* introduce WebWorker struct which is a stripped down version of cli::Worker
* refactored RecursiveLoad - it was renamed to RecursiveModuleLoad, it does not take ownership of isolate anymore - a struct implementing Stream that yields SourceCodeInfo
* untangled module loading logic between RecursiveLoad and isolate - that logic is encapsulated in EsIsolate and RecursiveModuleLoad, where isolate just consumes modules as they become available - does not require to pass Arc<Mutex<Isolate>> around anymore
* removed EsIsolate.mods_ in favor of Modules and moved them inside EsIsolate
* EsIsolate now requires "loader" argument during construction - struct that implements Loader trait
* rewrite first methods on isolate as async
tokio_util::run and tokio::run_on_current_thread should accept Future<Output=()> instead of Future<Output=Result<(), ()>>. Currently, all the passed futures have to add Ok(()) or futures::future::ok(()) unnecessarily to call this method.
- Remove ability to specify run arguments like `--allow-net` after the
script argument. It's too hacky to make work with clap.
- Remove `--v8-options`, instead use `--v8-flags=--help`
- Give more descriptive names to unit tests in flags.rs
- Assume argv and subcommand into DenoFlags struct so the output of
flags module is only DenoFlags rather than the tuple (subcommand, flags,
argv).
- Improve CLI help text
- Make `deno run` specific args like `--allow-net` only show up in 'deno
help run' instead of as global flags in `deno help`.
- Removes `deno version` to simplify our implementation and be closer to
clap defaults. `deno -V` now only shows Deno's version and not V8's nor
TypeScript. `Deno.versions` can be used to see that information.
- Prevent clap from auto-detecting terminal width and attempting to wrap
text.
This PR removes tokio_util::block_on - refactored compiler and file
fetcher slightly so that we can safely block there - that's because
only blocking path consist of only synchronous operations.
Additionally I removed excessive use of tokio_util::panic_on_error
and tokio_util::run_in_task and moved both functions to cli/worker.rs,
to tests module.
Closes #2960
After landing #3358 the benchmarks exploded indicating problems with workers and deno_core_http_bench.
This PR dramatically fixes thread/syscall count that showed up on benchmarks. Thread count is not back to previous levels but difference went from hundreds/thousands to about ~50.
- removes global `RESOURCE_TABLE` - resource tables are now created per `Worker`
in `State`
- renames `CliResource` to `StreamResource` and moves all logic related
to it to `cli/ops/io.rs`
- removes `cli/resources.rs`
- adds `state` argument to `op_read` and `op_write` and consequently adds
`stateful_minimal_op` to `State`
- IMPORTANT NOTE: workers don't have access to process stdio - this is
caused by fact that dropping worker would close stdout for process
(because it's constructed from raw handle, which closes underlying file
descriptor on drop)
This patch does not work with the recent bundler changes (#3325).
Unfortunately I didn't merge master before landing this patch. It has
something to do with console.log not working inside the compiler worker.
This reverts commit fd62379eaf.
- removes global `RESOURCE_TABLE` - resource tables are now created per `Worker`
in `State`
- renames `CliResource` to `StreamResource` and moves all logic related
to it to `cli/ops/io.rs`
- removes `cli/resources.rs`
- adds `state` argument to `op_read` and `op_write` and consequently adds
`stateful_minimal_op` to `State`
- IMPORTANT NOTE: workers don't have access to process stdio - this is
caused by fact that dropping worker would close stdout for process
(because it's constructed from raw handle, which closes underlying file
descriptor on drop)
- Bundles are fully standalone. They now include the shared loader with
`deno_typescript`.
- Refactor of the loader in `deno_typescript` to perform module
instantiation in a more
- Change of behaviour when an output file is not specified on the CLI.
Previously a default name was determined and the bundle written to that
file, now the bundle will be sent to `stdout`.
- Refactors in the TypeScript compiler to be able to support the concept
of a request type. This provides a cleaner abstraction and makes it
easier to support things like single module transpiles to the userland.
- Remove a "dangerous" circular dependency between `os.ts` and `deno.ts`,
and define `pid` and `noColor` in a better way.
- Don't bind early to `console` in `repl.ts`.
- Add an integration test for generating a bundle.
Towards simplifying (or better removing entirely) the CoreResource
trait. Resources should be any bit of privileged heap allocated memory
that needs to be referenced from JS, not very specific trait
implementations. Therefore CoreResource should be pushed towards being
as general as possible.
* Split ThreadSafeState into State and GlobalState. State is a "local"
state belonging to "Worker" while "GlobalState" is state shared by
whole program.
* Update "Worker" and ops to use "GlobalState" where applicable
* Move and refactor "WorkerChannels" resource
This avoids a crash when the Deno process has been running for
2**32 ms (about 50 days). Additionaly, time complexity of finding which
timer is due to fire next is reduced from from O(n) to O(log n).
Worth noting due to implementation of the Headers class the contents of headersMap have lowercase keys, although this matches the specification as header keys are case agnostic it does seem to not match behaviour of other implementations in other languages I have seen, would require some rewriting of Headers.ts
Basically this does pre-processing of TypeScript files and gathers all the
dependencies asynchronously. Only then after all the dependencies are gathered,
does it do a compile, which at that point all the dependencies are cached in
memory in the compiler, so with the exception of the hard coded assets, there
are no ops during the compilation.
Because op_fetch_source_files is now handled asynchronously in the runtime, we
can eliminate the tokio_util::block_on() which was causing the increase in
threads. Benchmarking on my machine has shown about a 5% improvement in speed
when dealing with compiling TypeScript. Still a long way to go, but an
improvement.
In theory the module name resolution and the fetching of the source files could
be broken out as two different ops. This would prevent situations of sending the
full source file all the time when actually the module is the same module
referenced by multiple modules, but that could be done subsequently to this.
When the global timer fires earlier than expected, which apparently
happens sometimes on server editions of Windows, we didn't call any
setTimeout callbacks, but we *also* didn't reschedule the global timer
to fire again later.
When this situation occurred it would make deno exit abruptly if there
were no other asynchronous ops running on the event loop. It could also
lead to application hangs if the upcoming setTimeout callback was
critical for the application to make progress.
This ensures the deno executable is properly created before running the integration tests.
Also allows deno_cli to be used as a lib. Docs are now properly generated: https://docs.rs/deno_cli/0.18.4/deno_cli/
Towards #2933
Prep for #2955
- Fixes cargo publish on deno_typescript, deno_cli_snapshots, and
deno_cli.
- Combines cli_snapshots and js into one directory.
- Extracts TS version at compile time rather than runtime
- Bumps version awkwardly - it was necessary to test end-to-end
publishing. Sorry.
- Adds git submodule deno_typescript/typescript
Instead of using core/snapshot_creator.rs, instead two crates are
introduced which allow building the snapshot during build.rs.
Rollup is removed and replaced with our own bundler. This removes
the Node build dependency. Modules in //js now use Deno-style imports
with file extensions, rather than Node style extensionless imports.
This improves incremental build time when changes are made to //js files
by about 40 seconds.
This removes dispatch_flatbuffers as it is now unused. There are still a
few places where msg_generated is used: ErrorKind and MediaType. These
will be dealt with later.
* Revert "port more ops to JSON (#2809)"
This reverts commit 137f33733d.
* Revert "port ops to JSON: compiler, errors, fetch, files (#2804)"
This reverts commit 79f82cf10e.
* Revert "Port rest of os ops to JSON (#2802)"
This reverts commit 5b2baa5c99.
* remove fetch_source_file_and_maybe_compile_async and
replace it with State.fetch_compiled_module
* remove SourceFile.js_source()
* introduce CompiledModule which is basically the same as
deno::SourceInfo and represents arbitrary file that has been
compiled to JS module
* introduce //cli/compilers module containing all compilers
* introduce JsCompiler which is a no-op compiler
- output is the same as input, no compilation takes place
- it is used for MediaType::JavaScript and MediaType::Unknown
* introduce JsonCompiler that wraps JSON in default export
* support JS-to-JS compilation using checkJs
* merge SourceFileFetcher trait and FileFetcher struct
* move logic related to source file fetching to //cli/file_fetcher.rs
* use Result when creating new ThreadSafeState
* rename `ModuleMetaData` to `SourceFile` and remove TS specific
functionality
* add `TsCompiler` struct encapsulating processing of TypeScript files
* move `SourceMapGetter` trait implementation to `//cli/compiler.rs`
* add low-level `DiskCache` API for general purpose caches and use it in
`DenoDir` and `TsCompiler` for filesystem access
* don't use hash-like filenames for compiled modules, instead use
metadata file for storing compilation hash
* add `SourceFileCache` for in-process caching of loaded files for fast
subsequent access
* define `SourceFileFetcher` trait encapsulating loading of local and
remote files and implement it for `DenoDir`
* define `use_cache` and `no_fetch` flags on `DenoDir` instead of using
in fetch methods
The rules are now as follows:
* In `import` statements, as mandated by the WHATWG specification,
the import specifier is always treated as a URL.
If it is a relative URL, it must start with either / or ./ or ../
* A script name passed to deno as a command line argument may be either
an absolute URL or a local path.
- If the name starts with a valid URI scheme followed by a colon, e.g.
'http:', 'https:', 'file:', 'foo+bar:', it always interpreted as a
URL (even if Deno doesn't support the indicated protocol).
- Otherwise, the script name is interpreted as a local path. The local
path may be relative, and operating system semantics determine how
it is resolved. Prefixing a relative path with ./ is not required.
A lot of its functionality is unused still, but the goal it to slowly
migrate logging functionality to it. There is also a useful progress bar
which can be ported over later - it depends on this module.
4c1fa54d10/src/cargo/util/progress.rs
1. Separate Snapshot and Script StartupData functions based on cfg "no-snapshot-init"
2. Replace deprecated Once::ONCE_INIT with Once::new (https://github.com/rust-lang/rust/pull/61757)
3. Elide lifetime
4. Fix typos
It's unnecessary indirection and is preventing the ability to easily
pass isolate references into the dispatch and dyn_import closures.
Note: this changes how StartupData::Script is executed. It's no longer done
during Isolate::new() but rather lazily on first poll or execution.
This patch makes it so that RecursiveLoad doesn't own the Isolate, so
Worker::execute_mod_async does not consume itself.
Previously Worker implemented Loader, but now ThreadSafeState does.
This is necessary preparation work for dynamic import (#1789) and import
maps (#1921)
* Compiler no longer has its own Tokio runtime. Compiler handles one
message and then exits.
* Uses the simpler ts.CompilerHost interface instead of
ts.LanguageServiceHost.
* avoids recompiling the same module by introducing a hacky but simple
`hashset<string>` that stores the module names that have been already
compiled.
* Removes the CompilerConfig op.
* Removes a lot of the mocking stuff in compiler.ts like `this._ts`. It
is not useful as we don't even have tests.
* Turns off checkJs because it causes fmt_test to die with OOM.
op_fetch_module_meta_data is an op that is used by the TypeScript
compiler. TypeScript requires this op to be sync. However the
implementation of the op does things on the event loop (like fetching
HTTP resources).
In certain situations this can lead to deadlocks. The runtime's thread
pool can be filled with ops waiting on the result of
op_fetch_module_meta_data. The runtime has a maximum number of
threads it can use (the number of logical CPUs on the system).
This patch changes tokio_util::block_on to launch a new Tokio runtime
for evaluating the future, thus bipassing the max-thread problem.
This is only an issue in op_fetch_module_meta_data. Other synchronous
ops are truly synchornous, not interacting with the event loop. TODO
comments are added to direct future development.
Removed `extmap` and added .mjs entry in `map_file_extension`.
The assert in the compiler does not need to be updated, since it is
resolving from the compiled cache instead of elsewhere (notice the .map
is asserted next to it)
* In order to prevent ArrayBuffers from getting garbage collected by V8,
we used to store a v8::Persistent<ArrayBuffer> in a map. This patch
introduces a custom ArrayBuffer allocator which doesn't use Persistent
handles, but instead stores a pointer to the actual ArrayBuffer data
alongside with a reference count. Since creating Persistent handles
has quite a bit of overhead, this change significantly increases
performance. Various HTTP server benchmarks report about 5-10% more
requests per second than before.
* Previously the Persistent handle that prevented garbage collection had
to be released manually, and this wasn't always done, which was
causing memory leaks. This has been resolved by introducing a new
`PinnedBuf` type in both Rust and C++ that automatically re-enables
garbage collection when it goes out of scope.
* Zero-copy buffers are now correctly wrapped in an Option if there is a
possibility that they're not present. This clears up a correctness
issue where we were creating zero-length slices from a null pointer,
which is against the rules.
Op dispatch is now dynamically dispatched, so slightly less efficient.
The immeasurable perf hit is a reasonable trade for the API simplicity
that is gained here.
* Moves how snapshots are supplied to the Isolate. Previously they were
given by Behavior::startup_data() but it was only called once at
startup. It makes more sense (and simplifies Behavior) to pass it to the
constructor of Isolate.
* Adds new libdeno type deno_snapshot instead of overloading
deno_buf.
* Adds new libdeno method to delete snapshot deno_snapshot_delete().
* Renames deno_get_snapshot() to deno_snapshot_new().
* Makes StartupData hold references to snapshots. This was implicit when
it previously held a deno_buf but is made explicit now. Note that
include_bytes!() returns a &'static [u8] and we want to avoid
copying that.
Fixes some sed errors introduced in c43cfe.
Unfortunately moving libdeno required splitting build.rs into two parts,
one for cli and one for core.
I've also removed the arm64 build - it's complicating things at this
re-org and we're not even testing it. I need to swing back to it and get
tools/test.py running for it.