profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/ry/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.

denoland/deno 76804

A secure JavaScript and TypeScript runtime

ry/deno 409

ry/deno_typescript 31

To generate snapshots of TypeScript files during build.rs

ry/awesome-deno 17

🎉A curated list of awesome things related to Deno

ry/eecs151 12

http://inst.eecs.berkeley.edu/~eecs151/fa19/

ry/aws-appsync-chat 10

Real-Time Offline Ready Chat App written with GraphQL, AWS AppSync, & AWS Amplify

ry/go 10

The Go programming language

push eventdenoland/deno

Aaron O'Mullan

commit sha 3e08b6ae89f9d29d5249345697fca6f86284bc3d

cleanup(runtime): remove last references to Deno.core.sharedQueue (#11503) `Deno.core.sharedQueue` was killed in #9843

view details

push time in 2 days

PR merged denoland/deno

cleanup(runtime): remove last references to Deno.core.sharedQueue

Deno.core.sharedQueue was killed in #9843

+0 -2

0 comment

1 changed file

AaronO

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...

SpencerSharkey

comment created time in 3 days

PullRequestReviewEvent

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?

SpencerSharkey

comment created time in 3 days

PullRequestReviewEvent

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

SpencerSharkey

comment created time in 3 days

pull request commentdenoland/rusty_v8

Add SharedIsolate w/ Locker API

@SpencerSharkey sorry for the delayed review - coming soon!

SpencerSharkey

comment created time in 3 days

push eventdenoland/deno_std

Fuji Haruka

commit sha 43ef9695693046465c9386f6e4a9d0249c562337

fix(encoding/toml): fix inline table and nested array (#1042)

view details

push time in 3 days

PR merged denoland/deno_std

fix(encoding/toml): fix inline table and nested array

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

+1474 -642

1 comment

12 changed files

FujiHaruka

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

danopia
PullRequestReviewEvent

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;+};

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?

pseudosavant

comment created time in 3 days

PullRequestReviewEvent
PullRequestReviewEvent

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)

Screen Shot 2021-07-21 at 1 16 47 PM

created time in 4 days

PullRequestReviewEvent

pull request commentdenoland/deno

chore: remove docs/ directory

Can you leave a file docs/README.md that points people to the new location?

bartlomieju

comment created time in 5 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

push eventdenobot2/deploy_demo

Ryan Dahl

commit sha 08bc01f09610f84f589cb30ffc830e824165c3b9

z

view details

push time in 6 days

push eventdenobot2/deploy_demo

Ryan Dahl

commit sha e65b9f5cbc08d6a8e6e1fe2a3f3229306e5e184c

y

view details

push time in 6 days

push eventdenobot2/deploy_demo

Ryan Dahl

commit sha 6c7e4eabfba91ad7d14494c74565c245b1cebdc8

x

view details

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...

pseudosavant

comment created time in 6 days

PullRequestReviewEvent
PullRequestReviewEvent

pull request commentdenoland/deno

feat: ffi to replace plugins

Reminder when landing to credit @manyuanrong as co-author (his original work was in https://github.com/denoland/deno/pull/9173)

eliassjogreen

comment created time in 6 days

push eventdenoland/deno

Ayato Tokubi

commit sha af4912ed0d1c679716c7776610a6b7eb4c806f85

fix(repl): output error without hanging when input is invalid (#11426)

view details

push time in 6 days