Issue 1:
Consider:

let connection = await Deno.connectTls({hostname: "google.com", port: 443})

// No ‘await’.
connection.read(new Uint8Array(2048))

await connection.write(new Uint8Array([0x0D, 0x0A]))
console.log("yo")

I’d expect the connection.write(...) promise to resolve eventually, but instead it does not (and the process blocks without ever logging "yo").

Issue 2:
The issue seems to be that Deno.startTls() resolves before the connection is fully setup - any writer created on the resulting tlsConnection will fail - here's a test:

import {
fail
} from "https://deno.land/std@0.83.0/testing/asserts.ts";
import { BufWriter } from "https://deno.land/std@0.83.0/io/mod.ts";

Deno.test("tls - raw tls upgrade", async () => {
interface Deferred<T> extends Promise<T> {
resolve: (value?: T | PromiseLike<T>) => void;
reject: (reason?: any) => void;
}

function deferred<T>(): Deferred<T> {
let methods = {};
const p = new Promise<T>((resolve, reject): void => {
methods = { resolve, reject };
});
return Object.assign(p, methods) as Deferred<T>;
}

const te = new TextEncoder();
const td = new TextDecoder();

function render(frame: Uint8Array): string {
const cr = "␍";
const lf = "␊";
return td.decode(frame)
.replace(/\n/g, lf)
.replace(/\r/g, cr);
}

async function write(writer: BufWriter, pm: string) {
try {
const buf = te.encode(pm);
const c = await writer.write(buf);
await writer.flush();
console.info(`< ${c}/${buf.length}:`, render(buf));
} catch (err) {
console.error(`error writing pm: ${pm}: ${err}`);
throw err;
}
}

const pong = deferred<void>();
const hostname = "demo.nats.io";
let conn = await Deno.connect({ hostname, port: 4443 });
const buf = new Uint8Array(64 * 1023);

let c = await conn.read(buf);
if (c === null) {
fail("connection closed");
}
//@ts-ignore - this has to be a number
const frame = buf.subarray(0, c);
console.info(">", render(frame));

// attempt the tls upgrade
console.info("upgrading connection");
const tlsConn = await Deno.startTls(conn, { hostname });
console.info("connection upgraded");

// start a reader to print server responses
let _ = (async function () {
while (true) {
try {
const c = await tlsConn.read(buf);
if (c === null) {
break;
}
if (c) {
const frame = buf.subarray(0, c);
console.info(">", render(frame));

const re = /^PONG\r\n/mi;
if (re.test(td.decode(frame))) {
pong.resolve();
}
}
} catch (err) {
// closed
break;
}
}
})();

const writer = new BufWriter(tlsConn);
await write(
writer,
`CONNECT {"protocol":1,"version":"1.0.0-13","lang":"nats.deno","verbose":false,"pedantic":true, "verbose":true}\r\n`,
);
await write(writer, `PING\r\n`);
await pong;
tlsConn.close();
});

Running with 1.4.6->1.6.1:

❯ deno --version
deno 1.4.6
v8 8.7.220.3
typescript 4.0.3
❯ deno test --allow-all --unstable --filter "tls - raw tls upgrade"
Check file:///Users/xxx/Dropbox/code/src/github.com/nats-io/nats.deno/$deno$test.ts
running 1 tests
test tls - raw tls upgrade ... > INFO {"server_id":"NDGMFJPAMLNEQNWVI5YRSEYMCPAU2SBIE6SCNE2I26CFRAUYBGSURRCU","server_name":"NDGMFJPAMLNEQNWVI5YRSEYMCPAU2SBIE6SCNE2I26CFRAUYBGSURRCU","version":"2.2.0-beta.35","proto":1,"go":"go1.15.6","host":"0.0.0.0","port":4443,"headers":true,"tls_required":true,"max_payload":1048576,"client_id":382,"client_ip":"71.193.91.14"} ␍␊
upgrading connection
connection upgraded
< 112/112: CONNECT {"protocol":1,"version":"1.0.0-13","lang":"nats.deno","verbose":false,"pedantic":true, "verbose":true}␍␊
< 6/6: PING␍␊
> +OK␍␊PONG␍␊
ok (367ms)

On 1.6.2+ the result is different - the code will block on the writer.flush():

❯ deno test --allow-all --unstable --filter "tls - raw tls upgrade"
Check file:///Users/xxx/Dropbox/code/src/github.com/nats-io/nats.deno/$deno$test.ts
running 1 tests
test tls - raw tls upgrade ... > INFO {"server_id":"NDGMFJPAMLNEQNWVI5YRSEYMCPAU2SBIE6SCNE2I26CFRAUYBGSURRCU","server_name":"NDGMFJPAMLNEQNWVI5YRSEYMCPAU2SBIE6SCNE2I26CFRAUYBGSURRCU","version":"2.2.0-beta.35","proto":1,"go":"go1.15.6","host":"0.0.0.0","port":4443,"headers":true,"tls_required":true,"max_payload":1048576,"client_id":383,"client_ip":"71.193.91.14"} ␍␊
upgrading connection
connection upgraded
^C

Removing the flush(), will make the program block as the read loop won't ever see the PONG\r\n response it is expecting.