Skip to content

Does this introduce a function coloring problem? #102

Open
@rictic

Description

This proposal introduces a new question whenever calling a function: what context should this function be run in?

There isn't a principled way of making this decision.

Consider a class:

import {f, g} from './qux.js';

class Foo {
  constructor() {
    // ...
  }

  bar() {
    f();
    g();
  }
}

When we call f and g in bar(), this class has at least two choices. It could call the function directly and keep the current context, or it could take a snapshot during construction and call f in that context. How can the author of Foo know which is appropriate? The answer doesn't need to be the same, f could require the constructor snapshot, and g could require the context that bar was called in. More problematically, bar might need to call a function that sometimes calls f and sometimes calls g.

This isn't a purely abstract concern, it came up while investigating using AsyncContext to power two APIs that are somewhat context-shaped. One is a DI system that flows down the tree of constructors, and the other is an event providence system (to answer questions like "what user interaction prompted this work"). Problems arise because a method on a class doesn't know when a function that it's calling may need to construct an object that participates in the DI system, so it's tempting to just run all of the class's work inside a snapshot taken at construction, but if it does that, then no other context can flow through the class, so work can't be reliably attributed to user interactions.

Taking a step back, it seems like this proposal introduces a function coloring problem – as described in What color is your function? – where a function's color is determined by its current call stack and the snapshots it has access to, there are N different colors, and there are few constraints on the relation defining which colors can call which. This information can't be known statically, and so there's limited ability for documentation or tooling to help. Taken together, I don't see how to build composable and reliable abstractions with AsyncContext.

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions