denoland/deno 76804
A secure JavaScript and TypeScript runtime
ry/deno 409
To generate snapshots of TypeScript files during build.rs
🎉A curated list of awesome things related to Deno
ry/eecs151 12
http://inst.eecs.berkeley.edu/~eecs151/fa19/
ry/april.kim 10
Real-Time Offline Ready Chat App written with GraphQL, AWS AppSync, & AWS Amplify
ry/go 10
The Go programming language
push eventdenoland/deno
commit sha 3e08b6ae89f9d29d5249345697fca6f86284bc3d
cleanup(runtime): remove last references to Deno.core.sharedQueue (#11503) `Deno.core.sharedQueue` was killed in #9843
push time in 2 days
PR merged denoland/deno
Deno.core.sharedQueue was killed in #9843
pr closed time in 2 days
Pull request review commentdenoland/rusty_v8
Add SharedIsolate w/ Locker API
impl IsolateHandle { } } +/// v8::Locker is a scoped lock object. While it's active, i.e. between its+/// construction and destruction, the current thread is allowed to use the locked+/// isolate. V8 guarantees that an isolate can be locked by at most one thread at+/// any time. In other words, the scope of a v8::Locker is a critical section.+///+/// rusty_v8 note: The Locker lifecycle is managed while a LockedIsolate is borrowed from a SharedIsolate.+#[derive(Debug)]+#[repr(C)]+pub struct Locker {+ has_lock: bool,+ top_level: bool,+ isolate: *mut Isolate,+}++impl Locker {+ /// Creates a locker using the provided Isolate pointer.+ /// Once created, the Locker is considered entered until dropped.+ pub(crate) unsafe fn new(isolate: *mut Isolate) -> Self {+ let mut locker = Self {+ has_lock: false,+ top_level: true,+ isolate,+ };+ v8__Locker__CONSTRUCT(&mut locker, isolate);+ locker+ }+}++impl Drop for Locker {+ fn drop(&mut self) {+ unsafe {+ v8__Locker__DESTRUCT(self);+ }+ }+}++/// The Unlocker object is intended for use in a long-running callback from V8, where you want to release the V8 lock for other threads to use.+/// The v8::Locker is a recursive lock, i.e. you can lock more than once in a given thread.+/// This can be useful if you have code that can be called either from code that holds the lock or from code that does not.+/// The Unlocker is not recursive so you can not have several Unlockers on the stack at once, and you can not use an Unlocker in a thread that is not inside a Locker's scope.+/// An unlocker will unlock several lockers if it has to and reinstate the correct depth of locking on its destruction+///+/// rusty_v8 note: By the nature of Rust's rules, the Unlocker is an inherently unsafe feature to use.+#[derive(Debug)]+#[repr(C)]+pub struct Unlocker<'a> {+ cxx_isolate: *mut Isolate,+ _lifetime: PhantomData<&'a ()>,+}++impl<'a> Unlocker<'a> {+ pub(crate) unsafe fn new(cxx_isolate: *mut Isolate) -> Self {+ let mut locker = Self {+ cxx_isolate,+ _lifetime: PhantomData::default(),+ };+ // the unlocker will exit any scopes (including ContextScopes), so we must do the same.+ (*cxx_isolate).exit();+ ScopeData::get_root_mut(&mut *cxx_isolate);+ // construct V8's native Unlocker instance+ v8__Unlocker__CONSTRUCT(&mut locker, cxx_isolate);+ locker+ }+}++impl<'a> Drop for Unlocker<'a> {+ fn drop(&mut self) {+ unsafe {+ v8__Unlocker__DESTRUCT(self);+ // restore the entered isolate+ (*self.cxx_isolate).enter();+ }+ }+}++/// An entered isolate within a Locker's scope. Created when a SharedIsolate is borrowed.+/// When dropped, the isolate is exited and the locker is deconstructed.+/// This is similar to V8's Isolate::Scope, but a Locker is implicitly entered for the life of a LockedIsolate.+pub struct LockedIsolate<'a> {+ cxx_isolate: &'a mut NonNull<Isolate>,+ locker: Locker,+}++impl<'a> LockedIsolate<'a> {+ /// Creates a new Locker scope and enters the isolate within, returning a scoped LockedIsolate.+ pub(crate) fn new(cxx_isolate: &'a mut NonNull<Isolate>) -> Self {+ let locker = unsafe {+ let locker = Locker::new(cxx_isolate.as_ptr());+ cxx_isolate.as_mut().enter();+ locker+ };+ Self {+ cxx_isolate,+ locker,+ }+ }++ /// Borrows a new Unlocker, temporarily releasing V8's lock on the current thread.+ /// The Unlocker exits the LockedIsolate and signals to V8 that the isolates locked to this thread may be used elsewhere.+ /// When the guard is dropped, the underlying Unlocker is destroyed and the isolate is re-entered.+ ///+ /// This function is marked unsafe because Rust's rules allow you to interact with other LockedIsolates while an Unlocker is active, which is not allowed.+ /// To make up for this limitation, the embedder should instead drop all active LockedIsolate references before doing long-lasting blocking work, re-entering afterwards.+ pub unsafe fn unlock(&mut self) -> Unlocker<'_> {+ Unlocker::new(self.cxx_isolate.as_mut())+ }+}++impl<'a> Deref for LockedIsolate<'a> {+ type Target = Isolate;+ fn deref(&self) -> &Self::Target {+ unsafe { self.cxx_isolate.as_ref() }+ }+}++impl<'a> DerefMut for LockedIsolate<'a> {+ fn deref_mut(&mut self) -> &mut Self::Target {+ unsafe { self.cxx_isolate.as_mut() }+ }+}++impl<'a> AsMut<Isolate> for LockedIsolate<'a> {+ fn as_mut(&mut self) -> &mut Isolate {+ self+ }+}++impl<'a> Drop for LockedIsolate<'a> {+ fn drop(&mut self) {+ // When a Locker is dropped, v8 automatically exits any active scopes.+ // Resetting to the root scope exits any zombie scopes so that the next LockedIsolate can cleanly re-enter a context.+ ScopeData::get_root_mut(self);+ unsafe { self.exit() }+ }+}++/// A reference to an Isolate that may be sent between threads and borrowed with a Locker before entering V8.+/// May be created by calling Isolate::new_shared(params), or converted via SharedIsolate::from(OwnedIsolate).+#[derive(Debug)]+pub struct SharedIsolate {+ cxx_isolate: NonNull<Isolate>,+ skip_disposal: bool,+}++// Because we only allow mutability through a borrowed LockedIsolate scope, we can safely send SharedIsolate across threads.+unsafe impl Send for SharedIsolate {}++impl SharedIsolate {+ /// Creates a new shared Isolate from a raw pointer.+ pub(crate) fn new(cxx_isolate: *mut Isolate) -> Self {+ Self {+ cxx_isolate: NonNull::new(cxx_isolate).unwrap(),+ skip_disposal: false,+ }+ }++ /// Borrows a LockedIsolate from the shared isolate reference.+ /// A Locker is created for the lifetime of the LockedIsolate, and the native isolate is entered.+ /// When the LockedIsolate is dropped, the isolate is and any entered scopes are exited, and the Locker is destroyed.+ pub fn lock(&mut self) -> LockedIsolate<'_> {+ LockedIsolate::new(&mut self.cxx_isolate)+ }+}++impl Deref for SharedIsolate {+ type Target = Isolate;++ fn deref(&self) -> &Self::Target {+ unsafe { self.cxx_isolate.as_ref() }+ }+}++impl From<OwnedIsolate> for SharedIsolate {+ /// Performs a conversion from an OwnedIsolate to a SharedIsolate.+ /// As the OwnedIsolate is dropped during conversion, active scopes and the native isolate are exited.+ fn from(mut isolate: OwnedIsolate) -> Self {+ // marking this as true will skip disposal of the native isolate, which is handed off to the SharedIsolate.+ isolate.skip_disposal = true;+ SharedIsolate::new(isolate.cxx_isolate.as_ptr())
This makes me wish we had LSAN working...
comment created time in 3 days
Pull request review commentdenoland/rusty_v8
Add SharedIsolate w/ Locker API
impl<T> Global<T> { } } +unsafe impl<T> Send for Global<T> {}
I don't think Global can safely be sent between threads?
comment created time in 3 days
Pull request review commentdenoland/rusty_v8
Add SharedIsolate w/ Locker API
impl IsolateHandle { } } +/// v8::Locker is a scoped lock object. While it's active, i.e. between its+/// construction and destruction, the current thread is allowed to use the locked+/// isolate. V8 guarantees that an isolate can be locked by at most one thread at+/// any time. In other words, the scope of a v8::Locker is a critical section.+///+/// rusty_v8 note: The Locker lifecycle is managed while a LockedIsolate is borrowed from a SharedIsolate.+#[derive(Debug)]+#[repr(C)]+pub struct Locker {+ has_lock: bool,+ top_level: bool,+ isolate: *mut Isolate,+}++impl Locker {+ /// Creates a locker using the provided Isolate pointer.+ /// Once created, the Locker is considered entered until dropped.+ pub(crate) unsafe fn new(isolate: *mut Isolate) -> Self {+ let mut locker = Self {+ has_lock: false,+ top_level: true,+ isolate,+ };+ v8__Locker__CONSTRUCT(&mut locker, isolate);+ locker+ }+}++impl Drop for Locker {+ fn drop(&mut self) {+ unsafe {+ v8__Locker__DESTRUCT(self);+ }+ }+}++/// The Unlocker object is intended for use in a long-running callback from V8, where you want to release the V8 lock for other threads to use.+/// The v8::Locker is a recursive lock, i.e. you can lock more than once in a given thread.+/// This can be useful if you have code that can be called either from code that holds the lock or from code that does not.+/// The Unlocker is not recursive so you can not have several Unlockers on the stack at once, and you can not use an Unlocker in a thread that is not inside a Locker's scope.+/// An unlocker will unlock several lockers if it has to and reinstate the correct depth of locking on its destruction
nit: please wrap at 80 columns
comment created time in 3 days
pull request commentdenoland/rusty_v8
Add SharedIsolate w/ Locker API
@SpencerSharkey sorry for the delayed review - coming soon!
comment created time in 3 days
push eventdenoland/deno_std
commit sha 43ef9695693046465c9386f6e4a9d0249c562337
fix(encoding/toml): fix inline table and nested array (#1042)
push time in 3 days
PR merged denoland/deno_std
close #823
Sorry for a large change. I almost overall rewrite TOML parser based on recursive descent parsing because current parser includes many edge case bugs. This will make the parser more stable and maintainable.
Of course all tests passed, by which we can believe the parser doesn't get worse. I also added some test cases the previous parser doesn't pass.
This PR fixes case 1, 2, 3, and 4 of https://github.com/denoland/deno_std/issues/823#issuecomment-814367934.
In addition, if the parser fails to parse, it outputs the position the error occurred like this:
Parse error on line 1, column 34: Single-line string cannot contain EOL
pr closed time in 3 days
issue closeddenoland/deno_std
TOML parser's inline/nested tables misaligned with real TOML
I'm comparing this TOML parse with http://toml-online-parser.ovonick.com
First opened here because I'm dumb: https://github.com/denoland/deno/issues/9919
case 1
This is proper TOML (AFAIK) that parses correctly elsewhere:
annotation_filter = { "kubernetes.io/ingress.class" = "nginx" }
... but Deno's parser tries reading as JSON:
> TOML.parse(`annotation_filter = { "kubernetes.io/ingress.class" = "nginx" }`);
error: Uncaught SyntaxError: Unexpected string in JSON at position 31
return JSON.parse(dataString);
^
at JSON.parse (<anonymous>)
at Parser._parseInlineTableOrArray (https://deno.land/[email protected]/encoding/toml.ts:322:19)
at Parser._parseData (https://deno.land/[email protected]/encoding/toml.ts:275:21)
at Parser._processDeclaration (https://deno.land/[email protected]/encoding/toml.ts:264:24)
at Parser._parseLines (https://deno.land/[email protected]/encoding/toml.ts:492:25)
at Parser.parse (https://deno.land/[email protected]/encoding/toml.ts:541:10)
at Module.parse (https://deno.land/[email protected]/encoding/toml.ts:735:33)
case 2
As a work around, I tried this non-inline syntax instead:
[[aaa]]
hi = "hi"
[aaa.bbb]
asdf = "asdf"
... but the key just silently gets lost:
> TOML.parse(`[[aaa]]\nhi = "hi"\n[aaa.bbb]\nasdf = "asdf"`)
{ aaa: [ { hi: "hi" } ] }
I was expecting:
{ "aaa": [ {
"hi": "hi",
"bbb": {
"asdf": "asdf"
}
} ] }
case 3
This actually works with Deno as of [email protected]:
[[source]]
annotation_filter = { "\"kubernetes.io/ingress.class\"": "nginx" }
# also this comment is read as a key because of leading spaces = "..."
That last line seems to be included because of some parsing bug:
> TOML.parse(`[[source]]\nannotation_filter = { "\\"kubernetes.io/ingress.class\\"": "nginx" }\n # also this comment is read as a key because of leading spaces = "..."`)
{
source: [
{
annotation_filter: { "kubernetes.io/ingress.class": "nginx" },
"# also this comment is read as a key because of leading spaces": "..."
}
]
}
That inline table is not valid TOML and yet it parses ok so I've been using it anyway 😒
closed time in 3 days
danopiaPull request review commentdenoland/deno_std
Add range request and etag support to `file_server.ts`
Deno.test("file_server should show .. if it makes sense", async function (): Pro await killFileServer(); } });++Deno.test(+ "file_server should download first byte of `hello.html` file",+ async () => {+ await startFileServer();+ try {+ const headers = {+ "range": "bytes=0-0",+ };+ const res = await fetch(+ "http://localhost:4507/testdata/test%20file.txt",+ { headers },+ );+ const text = await res.text();+ console.log(text);+ assertEquals(text, "L");+ } finally {+ await killFileServer();+ }+ },+);++Deno.test(+ "file_server sets `content-range` header for range request responses",+ async () => {+ await startFileServer();+ try {+ const headers = {+ "range": "bytes=0-100",+ };+ const res = await fetch(+ "http://localhost:4507/testdata/test%20file.txt",+ { headers },+ );+ const contentLength = await getTestFileSize();+ assertEquals(+ res.headers.get("content-range"),+ `bytes 0-100/${contentLength}`,+ );++ await res.text(); // Consuming the body so that the test doesn't leak resources+ } finally {+ await killFileServer();+ }+ },+);++const getTestFileSize = async () => {+ const fileInfo = await getTestFileStat();+ return fileInfo.size;+};++const getTestFileStat = async (): Promise<Deno.FileInfo> => {+ const fsPath = join(testdataDir, "test file.txt");+ const fileInfo = await Deno.stat(fsPath);++ return fileInfo;+};++const getTestFileEtag = async () => {+ const fileInfo = await getTestFileStat();++ if (fileInfo.mtime instanceof Date) {+ const lastModified = new Date(fileInfo.mtime);+ const simpleEtag = await createEtagHash(+ `${lastModified.toJSON()}${fileInfo.size}`,+ );+ return simpleEtag;+ } else {+ return "";+ }+};++const createEtagHash = async (message: string) => {+ // see: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest+ const hashType = "SHA-1"; // Faster, and this isn't a security senitive cryptographic use case+ const msgUint8 = new TextEncoder().encode(message);+ const hashBuffer = await crypto.subtle.digest(hashType, msgUint8);+ const hashArray = Array.from(new Uint8Array(hashBuffer));+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(+ "",+ );+ return hashHex;+};
That would work. But I question whether the test needs the ability to create the etag header generally - how about just hardcoding some expected etag values into the test?
comment created time in 3 days
issue openeddenoland/deno_website2
"Edit on Github" link on manual entries is broken
https://deno.land/[email protected]/getting_started/command_line_interface
click on github icon on top right
get sent to 404 https://github.com/denoland/manual/blob/v1.12.1/docs/getting_started/command_line_interface.md
created time in 4 days
issue openeddenoland/deno_website2
Twitter Card for Manual entries looks terrible
Try plugging a manual entry (like https://deno.land/[email protected]/tools/dependency_inspector) into the twitter card validator (https://cards-dev.twitter.com/validator)

created time in 4 days
pull request commentdenoland/deno
Can you leave a file docs/README.md that points people to the new location?
comment created time in 5 days
push eventdenobot2/deploy_demo
commit sha 08bc01f09610f84f589cb30ffc830e824165c3b9
z
push time in 6 days
push eventdenobot2/deploy_demo
commit sha e65b9f5cbc08d6a8e6e1fe2a3f3229306e5e184c
y
push time in 6 days
push eventdenobot2/deploy_demo
commit sha 6c7e4eabfba91ad7d14494c74565c245b1cebdc8
x
push time in 6 days
Pull request review commentdenoland/deno_std
Add range request and etag support to `file_server.ts`
Deno.test("file_server should show .. if it makes sense", async function (): Pro await killFileServer(); } });++Deno.test(+ "file_server should download first byte of `hello.html` file",+ async () => {+ await startFileServer();+ try {+ const headers = {+ "range": "bytes=0-0",+ };+ const res = await fetch(+ "http://localhost:4507/testdata/test%20file.txt",+ { headers },+ );+ const text = await res.text();+ console.log(text);+ assertEquals(text, "L");+ } finally {+ await killFileServer();+ }+ },+);++Deno.test(+ "file_server sets `content-range` header for range request responses",+ async () => {+ await startFileServer();+ try {+ const headers = {+ "range": "bytes=0-100",+ };+ const res = await fetch(+ "http://localhost:4507/testdata/test%20file.txt",+ { headers },+ );+ const contentLength = await getTestFileSize();+ assertEquals(+ res.headers.get("content-range"),+ `bytes 0-100/${contentLength}`,+ );++ await res.text(); // Consuming the body so that the test doesn't leak resources+ } finally {+ await killFileServer();+ }+ },+);++const getTestFileSize = async () => {+ const fileInfo = await getTestFileStat();+ return fileInfo.size;+};++const getTestFileStat = async (): Promise<Deno.FileInfo> => {+ const fsPath = join(testdataDir, "test file.txt");+ const fileInfo = await Deno.stat(fsPath);++ return fileInfo;+};++const getTestFileEtag = async () => {+ const fileInfo = await getTestFileStat();++ if (fileInfo.mtime instanceof Date) {+ const lastModified = new Date(fileInfo.mtime);+ const simpleEtag = await createEtagHash(+ `${lastModified.toJSON()}${fileInfo.size}`,+ );+ return simpleEtag;+ } else {+ return "";+ }+};++const createEtagHash = async (message: string) => {+ // see: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest+ const hashType = "SHA-1"; // Faster, and this isn't a security senitive cryptographic use case+ const msgUint8 = new TextEncoder().encode(message);+ const hashBuffer = await crypto.subtle.digest(hashType, msgUint8);+ const hashArray = Array.from(new Uint8Array(hashBuffer));+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(+ "",+ );+ return hashHex;+};
This code is duplicated... Seems better if you export it.
Also the .join("",) seems odd...
comment created time in 6 days
pull request commentdenoland/deno
Reminder when landing to credit @manyuanrong as co-author (his original work was in https://github.com/denoland/deno/pull/9173)
comment created time in 6 days
push eventdenoland/deno
commit sha af4912ed0d1c679716c7776610a6b7eb4c806f85
fix(repl): output error without hanging when input is invalid (#11426)
push time in 6 days